﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.templates;
using l1cs.server.model.Instance;
using l1cs.server.datatables;
using l1cs.server.serverpackets;
using l1cs.server.model.trap;
using l1cs.server.model.poison;
using System.Threading;

namespace l1cs.server.model.skill
{
    public class L1SkillUse
    {
        public const int TYPE_NORMAL = 0;
        public const int TYPE_LOGIN = 1;
        public const int TYPE_SPELLSC = 2;
        public const int TYPE_NPCBUFF = 3;
        public const int TYPE_GMBUFF = 4;

        private L1Skills _skill;
        private int _skillId;
        private int _getBuffDuration;
        private int _shockStunDuration;
        private int _getBuffIconDuration;
        private int _targetID;
        private int _mpConsume = 0;
        private int _hpConsume = 0;
        private int _targetX = 0;
        private int _targetY = 0;
        private String _message = null;
        private int _skillTime = 0;
        private int _type = 0;
        private bool _isPK = false;
        private int _bookmarkId = 0;
        private int _itemobjid = 0;
        private bool _checkedUseSkill = false; // 事前チェック済みか
        private int _leverage = 10; // 1/10倍なので10で1倍
        private bool _isFreeze = false;
        private bool _isCounterMagic = true;
        private bool _isGlanceCheckFail = false;

        private L1Character _user = null;
        private L1Character _target = null;

        private L1PcInstance _player = null;
        private L1NpcInstance _npc = null;
        private L1NpcInstance _targetNpc = null;

        private int _calcType;
        private const int PC_PC = 1;
        private const int PC_NPC = 2;
        private const int NPC_PC = 3;
        private const int NPC_NPC = 4;

        private List<TargetStatus> _targetList;

        private static Logger _log = Logger.getLogger( typeof( L1SkillUse ).FullName );

        private static int[] CAST_WITH_INVIS = { 1, 2, 3, 5, 8, 9, 12, 13,
			14, 19, 21, 26, 31, 32, 35, 37, 42, 43, 44, 48, 49, 52, 54, 55, 57,
			60, 61, 63, 67, 68, 69, 72, 73, 75, 78, 79, L1SkillId.REDUCTION_ARMOR,
			L1SkillId.BOUNCE_ATTACK, L1SkillId.SOLID_CARRIAGE, L1SkillId.COUNTER_BARRIER, 97, 98, 99, 100,
			101, 102, 104, 105, 106, 107, 109, 110, 111, 113, 114, 115, 116,
			117, 118, 129, 130, 131, 133, 134, 137, 138, 146, 147, 148, 149,
			150, 151, 155, 156, 158, 159, 163, 164, 165, 166, 168, 169, 170,
			171, L1SkillId.SOUL_OF_FLAME, L1SkillId.ADDITIONAL_FIRE, L1SkillId.DRAGON_SKIN, L1SkillId.AWAKEN_ANTHARAS,
			L1SkillId.AWAKEN_FAFURION, L1SkillId.AWAKEN_VALAKAS, L1SkillId.MIRROR_IMAGE, L1SkillId.ILLUSION_OGRE,
			L1SkillId.ILLUSION_LICH, L1SkillId.PATIENCE, L1SkillId.ILLUSION_DIA_GOLEM, L1SkillId.INSIGHT,
			L1SkillId.ILLUSION_AVATAR };

        private static int[] EXCEPT_COUNTER_MAGIC = { 1, 2, 3, 5, 8, 9, 12,
			13, 14, 19, 21, 26, 31, 32, 35, 37, 42, 43, 44, 48, 49, 52, 54, 55,
			57, 60, 61, 63, 67, 68, 69, 72, 73, 75, 78, 79, L1SkillId.SHOCK_STUN,
			L1SkillId.REDUCTION_ARMOR, L1SkillId.BOUNCE_ATTACK, L1SkillId.SOLID_CARRIAGE, L1SkillId.COUNTER_BARRIER,
			97, 98, 99, 100, 101, 102, 104, 105, 106, 107, 109, 110, 111, 113,
			114, 115, 116, 117, 118, 129, 130, 131, 132, 134, 137, 138, 146,
			147, 148, 149, 150, 151, 155, 156, 158, 159, 161, 163, 164, 165,
			166, 168, 169, 170, 171, L1SkillId.SOUL_OF_FLAME, L1SkillId.ADDITIONAL_FIRE,
			L1SkillId.DRAGON_SKIN, L1SkillId.FOE_SLAYER,
			L1SkillId.AWAKEN_ANTHARAS, L1SkillId.AWAKEN_FAFURION, L1SkillId.AWAKEN_VALAKAS,
			L1SkillId.MIRROR_IMAGE, L1SkillId.ILLUSION_OGRE, L1SkillId.ILLUSION_LICH, L1SkillId.PATIENCE, 10026, 10027,
			L1SkillId.ILLUSION_DIA_GOLEM, L1SkillId.INSIGHT, L1SkillId.ILLUSION_AVATAR, 10028, 10029 };

        public L1SkillUse()
        {
        }

        private class TargetStatus
        {
            private L1Character _target = null;
            private bool _isAction = false; // ダメージモーションが発生するか？
            private bool _isSendStatus = false; // キャラクターステータスを送信するか？（ヒール、スローなど状態が変わるとき送る）
            private bool _isCalc = true; // ダメージや確率魔法の計算をする必要があるか？

            public TargetStatus( L1Character _cha )
            {
                _target = _cha;
            }

            public TargetStatus( L1Character _cha, bool _flg )
            {
                _isCalc = _flg;
            }

            public L1Character getTarget()
            {
                return _target;
            }

            public bool isCalc()
            {
                return _isCalc;
            }

            public void isAction( bool _flg )
            {
                _isAction = _flg;
            }

            public bool isAction()
            {
                return _isAction;
            }

            public void isSendStatus( bool _flg )
            {
                _isSendStatus = _flg;
            }

            public bool isSendStatus()
            {
                return _isSendStatus;
            }
        }

        /*
         * 1/10倍で表現する。
         */
        public void setLeverage( int i )
        {
            _leverage = i;
        }

        public int getLeverage()
        {
            return _leverage;
        }

        private bool isCheckedUseSkill()
        {
            return _checkedUseSkill;
        }

        private void setCheckedUseSkill( bool flg )
        {
            _checkedUseSkill = flg;
        }

        public bool checkUseSkill( L1PcInstance player, int skillid,
                int target_id, int x, int y, String message, int time, int type, L1Character attacker )
        {
            // 初期設定ここから
            setCheckedUseSkill( true );
            _targetList = new List<TargetStatus>(); // ターゲットリストの初期化

            _skill = SkillsTable.getInstance().getTemplate( skillid );
            _skillId = skillid;
            _targetX = x;
            _targetY = y;
            _message = message;
            _skillTime = time;
            _type = type;
            bool checkedResult = true;

            if ( attacker == null )
            {
                // pc
                _player = player;
                _user = _player;
            }
            else
            {
                // npc
                _npc = (L1NpcInstance)attacker;
                _user = _npc;
            }

            if ( _skill.getTarget().Equals( "none" ) )
            {
                _targetID = _user.getId();
                _targetX = _user.getX();
                _targetY = _user.getY();
            }
            else
            {
                _targetID = target_id;
            }

            if ( type == TYPE_NORMAL )
            { // 通常の魔法使用時
                checkedResult = isNormalSkillUsable();
            }
            else if ( type == TYPE_SPELLSC )
            { // スペルスクロール使用時
                checkedResult = isSpellScrollUsable();
            }
            else if ( type == TYPE_NPCBUFF )
            {
                checkedResult = true;
            }
            if ( !checkedResult )
            {
                return false;
            }

            // ファイアーウォール、ライフストリームは詠唱対象が座標
            // キューブは詠唱者の座標に配置されるため例外
            if ( _skillId == L1SkillId.FIRE_WALL || _skillId == L1SkillId.LIFE_STREAM )
            {
                return true;
            }

            L1Object l1object = L1World.getInstance().findObject( _targetID );
            if ( l1object is L1ItemInstance )
            {
                _log.fine( "skill target item name: " + ( (L1ItemInstance)l1object ).getViewName() );
                // スキルターゲットが精霊の石になることがある。
                // Linux環境で確認（Windowsでは未確認）
                // 2008.5.4追記：地面のアイテムに魔法を使うとなる。継続してもエラーになるだけなのでreturn
                return false;
            }
            if ( _user is L1PcInstance )
            {
                if ( l1object is L1PcInstance )
                {
                    _calcType = PC_PC;
                }
                else
                {
                    _calcType = PC_NPC;
                    _targetNpc = (L1NpcInstance)l1object;
                }
            }
            else if ( _user is L1NpcInstance )
            {
                if ( l1object is L1PcInstance )
                {
                    _calcType = NPC_PC;
                }
                else if ( _skill.getTarget().Equals( "none" ) )
                {
                    _calcType = NPC_PC;
                }
                else
                {
                    _calcType = NPC_NPC;
                    _targetNpc = (L1NpcInstance)l1object;
                }
            }

            // テレポート、マステレポートは対象がブックマークID
            if ( _skillId == L1SkillId.TELEPORT || _skillId == L1SkillId.MASS_TELEPORT )
            {
                _bookmarkId = target_id;
            }
            // 対象がアイテムのスキル
            if ( _skillId == L1SkillId.CREATE_MAGICAL_WEAPON || _skillId == L1SkillId.BRING_STONE
             || _skillId == L1SkillId.BLESSED_ARMOR || _skillId == L1SkillId.ENCHANT_WEAPON
             || _skillId == L1SkillId.SHADOW_FANG )
            {
                _itemobjid = target_id;
            }
            _target = (L1Character)l1object;

            if ( !( _target is L1MonsterInstance )
                    && _skill.getTarget().Equals( "attack" )
                    && _user.getId() != target_id )
            {
                _isPK = true; // ターゲットがモンスター以外で攻撃系スキルで、自分以外の場合PKモードとする。
            }

            // 初期設定ここまで

            // 事前チェック
            if ( !( l1object is L1Character ) )
            { // ターゲットがキャラクター以外の場合何もしない。
                checkedResult = false;
            }
            makeTargetList(); // ターゲットの一覧を作成
            if ( _targetList.Count == 0 && ( _user is L1NpcInstance ) )
            {
                checkedResult = false;
            }
            // 事前チェックここまで
            return checkedResult;
        }

        /**
         * 通常のスキル使用時に使用者の状態からスキルが使用可能であるか判断する
         * 
         * @return false スキルが使用不可能な状態である場合
         */
        private bool isNormalSkillUsable()
        {
            // スキル使用者がPCの場合のチェック
            if ( _user is L1PcInstance )
            {
                L1PcInstance pc = (L1PcInstance)_user;

                if ( pc.isParalyzed() )
                { // 麻痺・凍結状態か
                    return false;
                }
                if ( ( pc.isInvisble() || pc.isInvisDelay() ) && !isInvisUsableSkill() )
                { // インビジ中に使用不可のスキル
                    return false;
                }
                if ( pc.getInventory().getWeight240() >= 197 )
                { // 重量オーバーならスキルを使用できない
                    pc.sendPackets( new S_ServerMessage( 316 ) );
                    return false;
                }
                int polyId = pc.getTempCharGfx();
                L1PolyMorph poly = PolyTable.getInstance().getTemplate( polyId );
                // 魔法が使えない変身
                if ( poly != null && !poly.canUseSkill() )
                {
                    pc.sendPackets( new S_ServerMessage( 285 ) ); // \f1その状態では魔法を使えません。
                    return false;
                }

                if ( !isAttrAgrees() )
                { // 精霊魔法で、属性が一致しなければ何もしない。
                    return false;
                }

                if ( _skillId == L1SkillId.ELEMENTAL_PROTECTION && pc.getElfAttr() == 0 )
                {
                    pc.sendPackets( new S_ServerMessage( 280 ) ); // \f1魔法が失敗しました。
                    return false;
                }

                // スキルディレイ中使用不可
                if ( pc.isSkillDelay() )
                {
                    return false;
                }

                // サイレンス状態では使用不可
                if ( pc.hasSkillEffect( L1SkillId.SILENCE )
                 || pc.hasSkillEffect( L1SkillId.AREA_OF_SILENCE )
                 || pc.hasSkillEffect( L1SkillId.STATUS_POISON_SILENCE ) )
                {
                    pc.sendPackets( new S_ServerMessage( 285 ) ); // \f1その状態では魔法を使えません。
                    return false;
                }

                // DIGはロウフルでのみ使用可
                if ( _skillId == L1SkillId.DISINTEGRATE && pc.getLawful() < 500 )
                {
                    // このメッセージであってるか未確認
                    pc.sendPackets( new S_ServerMessage( 352, "$967" ) ); // この魔法を利用するには性向値が%0でなければなりません。
                    return false;
                }

                // 同じキューブは効果範囲外であれば配置可能
                if ( _skillId == L1SkillId.CUBE_IGNITION || _skillId == L1SkillId.CUBE_QUAKE
                 || _skillId == L1SkillId.CUBE_SHOCK || _skillId == L1SkillId.CUBE_BALANCE )
                {
                    bool isNearSameCube = false;
                    int gfxId = 0;
                    foreach ( L1Object obj in L1World.getInstance()
                            .getVisibleObjects( pc, 3 ) )
                    {
                        if ( obj is L1EffectInstance )
                        {
                            L1EffectInstance effect = (L1EffectInstance)obj;
                            gfxId = effect.getGfxId();
                            if ( _skillId == L1SkillId.CUBE_IGNITION && gfxId == 6706
                             || _skillId == L1SkillId.CUBE_QUAKE && gfxId == 6712
                             || _skillId == L1SkillId.CUBE_SHOCK && gfxId == 6718
                             || _skillId == L1SkillId.CUBE_BALANCE && gfxId == 6724 )
                            {
                                isNearSameCube = true;
                                break;
                            }
                        }
                    }
                    if ( isNearSameCube )
                    {
                        pc.sendPackets( new S_ServerMessage( 1412 ) ); // すでに床にキューブが召喚されています。
                        return false;
                    }
                }

                // 覚醒状態では覚醒スキル以外使用不可
                if ( pc.getAwakeSkillId() == L1SkillId.AWAKEN_ANTHARAS
                        && _skillId != L1SkillId.AWAKEN_ANTHARAS && _skillId != L1SkillId.MAGMA_BREATH
                        && _skillId != L1SkillId.SHOCK_SKIN && _skillId != L1SkillId.FREEZING_BREATH
                        || pc.getAwakeSkillId() == L1SkillId.AWAKEN_FAFURION
                        && _skillId != L1SkillId.AWAKEN_FAFURION && _skillId != L1SkillId.MAGMA_BREATH
                        && _skillId != L1SkillId.SHOCK_SKIN && _skillId != L1SkillId.FREEZING_BREATH
                        || pc.getAwakeSkillId() == L1SkillId.AWAKEN_VALAKAS
                        && _skillId != L1SkillId.AWAKEN_VALAKAS && _skillId != L1SkillId.MAGMA_BREATH
                        && _skillId != L1SkillId.SHOCK_SKIN && _skillId != L1SkillId.FREEZING_BREATH )
                {
                    pc.sendPackets( new S_ServerMessage( 1385 ) ); // 現在の状態では覚醒魔法が使えません。
                    return false;
                }

                if ( isItemConsume() == false && !_player.isGm() )
                { // 消費アイテムはあるか
                    _player.sendPackets( new S_ServerMessage( 299 ) ); // 詠唱する材料がありません。
                    return false;
                }
            }
            // スキル使用者がNPCの場合のチェック
            else if ( _user is L1NpcInstance )
            {
                // サイレンス状態では使用不可
                if ( _user.hasSkillEffect( L1SkillId.SILENCE ) )
                {
                    // NPCにサイレンスが掛かっている場合は1回だけ使用をキャンセルさせる効果。
                    _user.removeSkillEffect( L1SkillId.SILENCE );
                    return false;
                }
            }

            // PC、NPC共通のチェック
            if ( !isHPMPConsume() )
            { // 消費HP、MPはあるか
                return false;
            }
            return true;
        }

        /**
         * スペルスクロール使用時に使用者の状態からスキルが使用可能であるか判断する
         * 
         * @return false スキルが使用不可能な状態である場合
         */
        private bool isSpellScrollUsable()
        {
            // スペルスクロールを使用するのはPCのみ
            L1PcInstance pc = (L1PcInstance)_user;

            if ( pc.isParalyzed() )
            { // 麻痺・凍結状態か
                return false;
            }

            // インビジ中に使用不可のスキル
            if ( ( pc.isInvisble() || pc.isInvisDelay() ) && !isInvisUsableSkill() )
            {
                return false;
            }

            return true;
        }

        // インビジ中に使用可能なスキルかを返す
        private bool isInvisUsableSkill()
        {
            foreach ( int skillId in CAST_WITH_INVIS )
            {
                if ( skillId == _skillId )
                {
                    return true;
                }
            }
            return false;
        }

        public void handleCommands( L1PcInstance player, int skillId, int targetId,
            int x, int y, String message, int timeSecs, int type )
        {
            L1Character attacker = null;
            handleCommands( player, skillId, targetId, x, y, message, timeSecs, type, attacker );
        }

        public void handleCommands( L1PcInstance player, int skillId, int targetId,
            int x, int y, String message, int timeSecs, int type, L1Character attacker )
        {
            // 事前チェックをしているか？
            if ( !isCheckedUseSkill() )
            {
                bool isUseSkill = checkUseSkill( player, skillId, targetId, x, y,
                    message, timeSecs, type, attacker );

                if ( !isUseSkill )
                {
                    failSkill();
                    return;
                }
            }

            if ( type == TYPE_NORMAL )
            { // 魔法詠唱時
                if ( !_isGlanceCheckFail || _skill.getArea() > 0 || _skill.getTarget().Equals( "none" ) )
                {
                    runSkill();
                    useConsume();
                    sendGrfx( true );
                    sendFailMessageHandle();
                    setDelay();
                }
            }
            else if ( type == TYPE_LOGIN )
            { // ログイン時（HPMP材料消費なし、グラフィックなし）
                runSkill();
            }
            else if ( type == TYPE_SPELLSC )
            { // スペルスクロール使用時（HPMP材料消費なし）
                runSkill();
                sendGrfx( true );
            }
            else if ( type == TYPE_GMBUFF )
            { // GMBUFF使用時（HPMP材料消費なし、魔法モーションなし）
                runSkill();
                sendGrfx( false );
            }
            else if ( type == TYPE_NPCBUFF )
            { // NPCBUFF使用時（HPMP材料消費なし）
                runSkill();
                sendGrfx( true );
            }
            setCheckedUseSkill( false );

        }

        /**
         * スキルの失敗処理(PCのみ）
         */
        private void failSkill()
        {
            // HPが足りなくてスキルが使用できない場合のみ、MPのみ消費したいが未実装（必要ない？）
            // その他の場合は何も消費されない。
            // useConsume(); // HP、MPは減らす
            setCheckedUseSkill( false );
            // テレポートスキル
            if ( _skillId == L1SkillId.TELEPORT || _skillId == L1SkillId.MASS_TELEPORT
             || _skillId == L1SkillId.TELEPORT_TO_MATHER )
            {
                // テレポートできない場合でも、クライアント側は応答を待っている
                // テレポート待ち状態の解除（第2引数に意味はない）
                _player.sendPackets( new S_Paralysis( S_Paralysis.TYPE_TELEPORT_UNLOCK, false ) );
            }
        }

        // ターゲットか？
        private bool isTarget( L1Character cha )
        {
            bool _flg = false;

            if ( cha is L1PcInstance )
            {
                L1PcInstance pc = (L1PcInstance)cha;
                if ( pc.isGhost() || pc.isGmInvis() )
                {
                    return false;
                }
            }
            if ( _calcType == NPC_PC && ( cha is L1PcInstance || cha is L1PetInstance || cha is L1SummonInstance ) )
            {
                _flg = true;
            }

            // 破壊不可能なドアは対象外
            if ( cha is L1DoorInstance )
            {
                if ( cha.getMaxHp() == 0 || cha.getMaxHp() == 1 )
                {
                    return false;
                }
            }

            // マジックドールは対象外
            if ( cha is L1DollInstance && _skillId != L1SkillId.HASTE )
            {
                return false;
            }

            // 元のターゲットがPet、Summon以外のNPCの場合、PC、Pet、Summonは対象外
            if ( _calcType == PC_NPC
                    && _target is L1NpcInstance
                    && !( _target is L1PetInstance )
                    && !( _target is L1SummonInstance )
                    && ( cha is L1PetInstance
                            || cha is L1SummonInstance || cha is L1PcInstance ) )
            {
                return false;
            }

            // 元のターゲットがガード以外のNPCの場合、ガードは対象外
            if ( _calcType == PC_NPC
                    && _target is L1NpcInstance
                    && !( _target is L1GuardInstance )
                    && cha is L1GuardInstance )
            {
                return false;
            }

            // NPC対PCでターゲットがモンスターの場合ターゲットではない。
            if ( ( _skill.getTarget().Equals( "attack" ) || _skill.getType() == L1Skills.TYPE_ATTACK )
                    && _calcType == NPC_PC
                    && !( cha is L1PetInstance )
                    && !( cha is L1SummonInstance )
                    && !( cha is L1PcInstance ) )
            {
                return false;
            }

            // NPC対NPCで使用者がMOBで、ターゲットがMOBの場合ターゲットではない。
            if ( ( _skill.getTarget().Equals( "attack" )
                    || _skill.getType() == L1Skills.TYPE_ATTACK )
                    && _calcType == NPC_NPC
                    && _user is L1MonsterInstance
                    && cha is L1MonsterInstance )
            {
                return false;
            }

            // 無方向範囲攻撃魔法で攻撃できないNPCは対象外
            if ( _skill.getTarget().Equals( "none" )
                    && _skill.getType() == L1Skills.TYPE_ATTACK
                    && ( cha is L1AuctionBoardInstance
                            || cha is L1BoardInstance
                            || cha is L1CrownInstance
                            || cha is L1DwarfInstance
                            || cha is L1EffectInstance
                            || cha is L1FieldObjectInstance
                            || cha is L1FurnitureInstance
                            || cha is L1HousekeeperInstance
                            || cha is L1MerchantInstance
                            || cha is L1TeleporterInstance ) )
            {
                return false;
            }

            // 攻撃系スキルで対象が自分は対象外
            if ( _skill.getType() == L1Skills.TYPE_ATTACK
                    && cha.getId() == _user.getId() )
            {
                return false;
            }

            // ターゲットが自分でH-Aの場合効果無し
            if ( cha.getId() == _user.getId() && _skillId == L1SkillId.HEAL_ALL )
            {
                return false;
            }

            if ( ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_PC ) == L1Skills.TARGET_TO_PC
                    || ( _skill.getTargetTo() & L1Skills.TARGET_TO_CLAN ) == L1Skills.TARGET_TO_CLAN || ( _skill
                    .getTargetTo() & L1Skills.TARGET_TO_PARTY ) == L1Skills.TARGET_TO_PARTY )
                    && cha.getId() == _user.getId() && _skillId != L1SkillId.HEAL_ALL )
            {
                return true; // ターゲットがパーティーかクラン員のものは自分に効果がある。（ただし、ヒールオールは除外）
            }

            // スキル使用者がPCで、PKモードではない場合、自分のサモン・ペットは対象外
            if ( _user is L1PcInstance
                    && ( _skill.getTarget().Equals( "attack" ) || _skill.getType() == L1Skills.TYPE_ATTACK )
                    && _isPK == false )
            {
                if ( cha is L1SummonInstance )
                {
                    L1SummonInstance summon = (L1SummonInstance)cha;
                    if ( _player.getId() == summon.getMaster().getId() )
                    {
                        return false;
                    }
                }
                else if ( cha is L1PetInstance )
                {
                    L1PetInstance pet = (L1PetInstance)cha;
                    if ( _player.getId() == pet.getMaster().getId() )
                    {
                        return false;
                    }
                }
            }

            if ( ( _skill.getTarget().Equals( "attack" )
                    || _skill.getType() == L1Skills.TYPE_ATTACK )
                    && !( cha is L1MonsterInstance )
                    && _isPK == false
                    && _target is L1PcInstance )
            {
                L1PcInstance enemy = (L1PcInstance)cha;
                // カウンターディテクション
                if ( _skillId == L1SkillId.COUNTER_DETECTION && enemy.getZoneType() != 1
                        && ( cha.hasSkillEffect( L1SkillId.INVISIBILITY )
                        || cha.hasSkillEffect( L1SkillId.BLIND_HIDING ) ) )
                {
                    return true; // インビジかブラインドハイディング中
                }
                if ( _player.getClanid() != 0 && enemy.getClanid() != 0 )
                { // クラン所属中
                    // 全戦争リストを取得
                    foreach ( L1War war in L1World.getInstance().getWarList() )
                    {
                        if ( war.CheckClanInWar( _player.getClanname() ) )
                        { // 自クランが戦争に参加中
                            if ( war.CheckClanInSameWar( _player.getClanname(), enemy.getClanname() ) )// 同じ戦争に参加中
                            {
                                if ( L1CastleLocation.checkInAllWarArea( enemy.getX(), enemy.getY(), enemy.getMapId() ) )
                                {
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false; // 攻撃スキルでPKモードじゃない場合
            }

            if ( _user.glanceCheck( cha.getX(), cha.getY() ) == false
                    && _skill.isThrough() == false )
            {
                // エンチャント、復活スキルは障害物の判定をしない
                if ( !( _skill.getType() == L1Skills.TYPE_CHANGE
                        || _skill.getType() == L1Skills.TYPE_RESTORE ) )
                {
                    _isGlanceCheckFail = true;
                    return false; // 直線上に障害物がある
                }
            }

            if ( cha.hasSkillEffect( L1SkillId.ICE_LANCE )
                    && ( _skillId == L1SkillId.ICE_LANCE || _skillId == L1SkillId.FREEZING_BLIZZARD
                            || _skillId == L1SkillId.FREEZING_BREATH ) )
            {
                return false; // アイスランス中にアイスランス、フリージングブリザード、フリージングブレス
            }

            if ( cha.hasSkillEffect( L1SkillId.FREEZING_BLIZZARD )
                    && ( _skillId == L1SkillId.ICE_LANCE || _skillId == L1SkillId.FREEZING_BLIZZARD
                            || _skillId == L1SkillId.FREEZING_BREATH ) )
            {
                return false; // フリージングブリザード中にアイスランス、フリージングブリザード、フリージングブレス
            }

            if ( cha.hasSkillEffect( L1SkillId.FREEZING_BREATH )
                    && ( _skillId == L1SkillId.ICE_LANCE || _skillId == L1SkillId.FREEZING_BLIZZARD
                            || _skillId == L1SkillId.FREEZING_BREATH ) )
            {
                return false; // フリージングブレス中にアイスランス、フリージングブリザード、フリージングブレス
            }

            if ( cha.hasSkillEffect( L1SkillId.EARTH_BIND ) && _skillId == L1SkillId.EARTH_BIND )
            {
                return false; // アース バインド中にアース バインド
            }

            if ( !( cha is L1MonsterInstance )
                    && ( _skillId == L1SkillId.TAMING_MONSTER || _skillId == L1SkillId.CREATE_ZOMBIE ) )
            {
                return false; // ターゲットがモンスターじゃない（テイミングモンスター）
            }
            if ( cha.isDead()
                    && ( _skillId != L1SkillId.CREATE_ZOMBIE
                    && _skillId != L1SkillId.RESURRECTION
                    && _skillId != L1SkillId.GREATER_RESURRECTION
                    && _skillId != L1SkillId.CALL_OF_NATURE ) )
            {
                return false; // ターゲットが死亡している
            }

            if ( cha.isDead() == false
                    && ( _skillId == L1SkillId.CREATE_ZOMBIE
                    || _skillId == L1SkillId.RESURRECTION
                    || _skillId == L1SkillId.GREATER_RESURRECTION
                    || _skillId == L1SkillId.CALL_OF_NATURE ) )
            {
                return false; // ターゲットが死亡していない
            }

            if ( ( cha is L1TowerInstance || cha is L1DoorInstance )
                    && ( _skillId == L1SkillId.CREATE_ZOMBIE
                    || _skillId == L1SkillId.RESURRECTION
                    || _skillId == L1SkillId.GREATER_RESURRECTION
                    || _skillId == L1SkillId.CALL_OF_NATURE ) )
            {
                return false; // ターゲットがガーディアンタワー、ドア
            }

            if ( cha is L1PcInstance )
            {
                L1PcInstance pc = (L1PcInstance)cha;
                if ( pc.hasSkillEffect( L1SkillId.ABSOLUTE_BARRIER ) )
                { // アブソルートバリア中
                    if ( _skillId == L1SkillId.CURSE_BLIND || _skillId == L1SkillId.WEAPON_BREAK
                            || _skillId == L1SkillId.DARKNESS || _skillId == L1SkillId.WEAKNESS
                            || _skillId == L1SkillId.DISEASE || _skillId == L1SkillId.FOG_OF_SLEEPING
                            || _skillId == L1SkillId.MASS_SLOW || _skillId == L1SkillId.SLOW
                            || _skillId == L1SkillId.CANCELLATION || _skillId == L1SkillId.SILENCE
                            || _skillId == L1SkillId.DECAY_POTION || _skillId == L1SkillId.MASS_TELEPORT
                            || _skillId == L1SkillId.DETECTION
                            || _skillId == L1SkillId.COUNTER_DETECTION
                            || _skillId == L1SkillId.ERASE_MAGIC || _skillId == L1SkillId.ENTANGLE
                            || _skillId == L1SkillId.PHYSICAL_ENCHANT_DEX
                            || _skillId == L1SkillId.PHYSICAL_ENCHANT_STR
                            || _skillId == L1SkillId.BLESS_WEAPON || _skillId == L1SkillId.EARTH_SKIN
                            || _skillId == L1SkillId.IMMUNE_TO_HARM
                            || _skillId == L1SkillId.REMOVE_CURSE )
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            if ( cha is L1NpcInstance )
            {
                int hiddenStatus = ( (L1NpcInstance)cha ).getHiddenStatus();
                if ( hiddenStatus == L1NpcInstance.HIDDEN_STATUS_SINK )
                {
                    if ( _skillId == L1SkillId.DETECTION || _skillId == L1SkillId.COUNTER_DETECTION )
                    { // ディテク、Cディテク
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else if ( hiddenStatus == L1NpcInstance.HIDDEN_STATUS_FLY )
                {
                    return false;
                }
            }

            if ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_PC ) == L1Skills.TARGET_TO_PC // ターゲットがPC
                    && cha is L1PcInstance )
            {
                _flg = true;
            }
            else if ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_NPC ) == L1Skills.TARGET_TO_NPC // ターゲットがNPC
                  && ( cha is L1MonsterInstance
                          || cha is L1NpcInstance
                          || cha is L1SummonInstance || cha is L1PetInstance ) )
            {
                _flg = true;
            }
            else if ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_PET ) == L1Skills
                  .TARGET_TO_PET && _user is L1PcInstance )
            { // ターゲットがSummon,Pet
                if ( cha is L1SummonInstance )
                {
                    L1SummonInstance summon = (L1SummonInstance)cha;
                    if ( summon.getMaster() != null )
                    {
                        if ( _player.getId() == summon.getMaster().getId() )
                        {
                            _flg = true;
                        }
                    }
                }
                if ( cha is L1PetInstance )
                {
                    L1PetInstance pet = (L1PetInstance)cha;
                    if ( pet.getMaster() != null )
                    {
                        if ( _player.getId() == pet.getMaster().getId() )
                        {
                            _flg = true;
                        }
                    }
                }
            }

            if ( _calcType == PC_PC && cha is L1PcInstance )
            {
                if ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_CLAN ) == L1Skills.TARGET_TO_CLAN
                 && ( ( _player.getClanid() != 0 // ターゲットがクラン員
                 && _player.getClanid() == ( (L1PcInstance)cha ).getClanid() ) || _player.isGm() ) )
                {
                    return true;
                }
                if ( ( _skill.getTargetTo() & L1Skills.TARGET_TO_PARTY ) == L1Skills.TARGET_TO_PARTY
                 && ( _player.getParty().isMember( (L1PcInstance)cha ) || _player.isGm() ) )// ターゲットがパーティー
                {
                    return true;
                }
            }

            return _flg;
        }

        // ターゲットの一覧を作成
        private void makeTargetList()
        {

            if ( _type == TYPE_LOGIN )
            { // ログイン時(死亡時、お化け屋敷のキャンセレーション含む)は使用者のみ
                _targetList.Add( new TargetStatus( _user ) );
                return;
            }
            if ( _skill.getTargetTo() == L1Skills.TARGET_TO_ME
                    && ( _skill.getType() & L1Skills.TYPE_ATTACK ) != L1Skills.TYPE_ATTACK )
            {
                _targetList.Add( new TargetStatus( _user ) ); // ターゲットは使用者のみ
                return;
            }

            // 射程距離-1の場合は画面内のオブジェクトが対象
            if ( _skill.getRanged() != -1 )
            {
                if ( _user.getLocation().getTileLineDistance(
                        _target.getLocation() ) > _skill.getRanged() )
                {
                    return; // 射程範囲外
                }
            }
            else
            {
                if ( !_user.getLocation().isInScreen( _target.getLocation() ) )
                {
                    return; // 射程範囲外
                }
            }

            if ( isTarget( _target ) == false
                    && !( _skill.getTarget().Equals( "none" ) ) )
            {
                // 対象が違うのでスキルが発動しない。
                return;
            }

            if ( _skillId == L1SkillId.LIGHTNING || _skillId == L1SkillId.FREEZING_BREATH )
            { // ライトニング、フリージングブレス直線的に範囲を決める
                List<L1Object> al1object = L1World.getInstance().getVisibleLineObjects( _user, _target );

                foreach ( L1Object tgobj in al1object )
                {
                    if ( tgobj == null )
                    {
                        continue;
                    }
                    if ( !( tgobj is L1Character ) )
                    { // ターゲットがキャラクター以外の場合何もしない。
                        continue;
                    }
                    L1Character cha = (L1Character)tgobj;
                    if ( isTarget( cha ) == false )
                    {
                        continue;
                    }
                    _targetList.Add( new TargetStatus( cha ) );
                }
                return;
            }

            if ( _skill.getArea() == 0 )
            { // 単体の場合
                if ( !_user.glanceCheck( _target.getX(), _target.getY() ) )
                { // 直線上に障害物があるか
                    if ( ( _skill.getType() & L1Skills.TYPE_ATTACK ) == L1Skills
                            .TYPE_ATTACK && _skillId != 10026
                            && _skillId != 10027 && _skillId != 10028
                            && _skillId != 10029 )
                    { // 安息攻撃以外の攻撃スキル
                        _targetList.Add( new TargetStatus( _target, false ) ); // ダメージも発生しないし、ダメージモーションも発生しないが、スキルは発動
                        return;
                    }
                }
                _targetList.Add( new TargetStatus( _target ) );
            }
            else
            { // 範囲の場合
                if ( !_skill.getTarget().Equals( "none" ) )
                {
                    _targetList.Add( new TargetStatus( _target ) );
                }

                if ( _skillId != 49
                        && !( _skill.getTarget().Equals( "attack" ) || _skill
                                .getType() == L1Skills.TYPE_ATTACK ) )
                {
                    // 攻撃系以外のスキルとH-A以外はターゲット自身を含める
                    _targetList.Add( new TargetStatus( _user ) );
                }

                List<L1Object> objects;
                if ( _skill.getArea() == -1 )
                {
                    objects = L1World.getInstance().getVisibleObjects( _user );
                }
                else
                {
                    objects = L1World.getInstance().getVisibleObjects( _target, _skill.getArea() );
                }
                foreach ( L1Object tgobj in objects )
                {
                    if ( tgobj == null )
                    {
                        continue;
                    }
                    if ( !( tgobj is L1Character ) )
                    { // ターゲットがキャラクター以外の場合何もしない。
                        continue;
                    }
                    L1Character cha = (L1Character)tgobj;
                    if ( !isTarget( cha ) )
                    {
                        continue;
                    }

                    _targetList.Add( new TargetStatus( cha ) );
                }
                return;
            }


        }

        // メッセージの表示（何か起こったとき）
        private void sendHappenMessage( L1PcInstance pc )
        {
            int msgID = _skill.getSysmsgIdHappen();
            if ( msgID > 0 )
            {
                pc.sendPackets( new S_ServerMessage( msgID ) );
            }
        }

        // 失敗メッセージ表示のハンドル
        private void sendFailMessageHandle()
        {
            // 攻撃スキル以外で対象を指定するスキルが失敗した場合は失敗したメッセージをクライアントに送信
            // ※攻撃スキルは障害物があっても成功時と同じアクションであるべき。
            if ( _skill.getType() != L1Skills.TYPE_ATTACK
                    && !_skill.getTarget().Equals( "none" )
                    && _targetList.Count == 0 )
            {
                sendFailMessage();
            }
        }

        // メッセージの表示（失敗したとき）
        private void sendFailMessage()
        {
            int msgID = _skill.getSysmsgIdFail();
            if ( msgID > 0 && ( _user is L1PcInstance ) )
            {
                _player.sendPackets( new S_ServerMessage( msgID ) );
            }
        }

        // 精霊魔法の属性と使用者の属性は一致するか？（とりあえずの対処なので、対応できたら消去して下さい)
        private bool isAttrAgrees()
        {
            int magicattr = _skill.getAttr();
            if ( _user is L1NpcInstance )
            { // NPCが使った場合なんでもOK
                return true;
            }

            if ( _skill.getSkillLevel() >= 17 && _skill.getSkillLevel() <= 22
                    && magicattr != 0 // 精霊魔法で、無属性魔法ではなく、
                    && magicattr != _player.getElfAttr() // 使用者と魔法の属性が一致しない。
                    && !_player.isGm() )
            { // ただしGMは例外
                return false;
            }
            return true;
        }

        /**
         * スキルを使用するために必要なHPがあるか返す。
         * 
         * @return HPが十分であればtrue
         */
        private bool isEnoughHp()
        {
            return false;
        }

        /**
         * スキルを使用するために必要なMPがあるか返す。
         * 
         * @return MPが十分であればtrue
         */
        private bool isEnoughMp()
        {
            return false;
        }

        // 必要ＨＰ、ＭＰがあるか？
        private bool isHPMPConsume()
        {
            _mpConsume = _skill.getMpConsume();
            _hpConsume = _skill.getHpConsume();
            int currentMp = 0;
            int currentHp = 0;

            if ( _user is L1NpcInstance )
            {
                currentMp = _npc.getCurrentMp();
                currentHp = _npc.getCurrentHp();
            }
            else
            {
                currentMp = _player.getCurrentMp();
                currentHp = _player.getCurrentHp();

                // MPのINT軽減
                if ( _player.getInt() > 12
                        && _skillId > L1SkillId.HOLY_WEAPON
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV2以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 13
                        && _skillId > L1SkillId.STALAC
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV3以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 14
                        && _skillId > L1SkillId.WEAK_ELEMENTAL
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV4以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 15
                        && _skillId > L1SkillId.MEDITATION
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV5以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 16
                        && _skillId > L1SkillId.DARKNESS
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV6以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 17
                        && _skillId > L1SkillId.BLESS_WEAPON
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV7以上
                    _mpConsume--;
                }
                if ( _player.getInt() > 18
                        && _skillId > L1SkillId.DISEASE
                        && _skillId <= L1SkillId.FREEZING_BLIZZARD )
                { // LV8以上
                    _mpConsume--;
                }

                if ( _player.getInt() > 12
                        && _skillId >= L1SkillId.SHOCK_STUN && _skillId <= L1SkillId.COUNTER_BARRIER )
                {
                    _mpConsume -= ( _player.getInt() - 12 );
                }

                // MPの装備軽減
                if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_DEX && _player.getInventory().checkEquipped( 20013 ) )
                { // 迅速ヘルム装備中にPE:DEX
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.HASTE && _player.getInventory().checkEquipped( 20013 ) )
                { // 迅速ヘルム装備中にヘイスト
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.HEAL && _player.getInventory().checkEquipped( 20014 ) )
                { // 治癒ヘルム装備中にヒール
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.EXTRA_HEAL && _player.getInventory().checkEquipped( 20014 ) )
                { // 治癒ヘルム装備中にエキストラヒール
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.ENCHANT_WEAPON && _player.getInventory().checkEquipped( 20015 ) )
                { // 力ヘルム装備中にエンチャントウエポン
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.DETECTION && _player.getInventory().checkEquipped( 20015 ) )
                { // 力ヘルム装備中にディテクション
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_STR && _player.getInventory().checkEquipped( 20015 ) )
                { // 力ヘルム装備中にPE:STR
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.HASTE && _player.getInventory().checkEquipped( 20008 ) )
                { // マイナーウィンドヘルム装備中にヘイスト
                    _mpConsume /= 2;
                }
                if ( _skillId == L1SkillId.GREATER_HASTE && _player.getInventory().checkEquipped( 20023 ) )
                { // ウィンドヘルム装備中にグレーターヘイスト
                    _mpConsume /= 2;
                }

                if ( 0 < _skill.getMpConsume() )
                { // MPを消費するスキルであれば
                    _mpConsume = Math.Max( _mpConsume, 1 ); // 最低でも1消費する。
                }

                // MPのオリジナルINT軽減
                if ( _player.getOriginalMagicConsumeReduction() > 0 )
                {
                    _mpConsume -= _player.getOriginalMagicConsumeReduction();
                }
            }

            if ( currentHp < _hpConsume + 1 )
            {
                if ( _user is L1PcInstance )
                {
                    _player.sendPackets( new S_ServerMessage( 279 ) );
                }
                return false;
            }
            else if ( currentMp < _mpConsume )
            {
                if ( _user is L1PcInstance )
                {
                    _player.sendPackets( new S_ServerMessage( 278 ) );
                }
                return false;
            }

            return true;
        }

        // 必要材料があるか？
        private bool isItemConsume()
        {

            int itemConsume = _skill.getItemConsumeId();
            int itemConsumeCount = _skill.getItemConsumeCount();

            if ( itemConsume == 0 )
            {
                return true; // 材料を必要としない魔法
            }

            if ( !_player.getInventory().checkItem( itemConsume, itemConsumeCount ) )
            {
                return false; // 必要材料が足りなかった。
            }

            return true;
        }

        // 使用材料、HP・MP、Lawfulをマイナスする。
        private void useConsume()
        {
            if ( _user is L1NpcInstance )
            {
                // NPCの場合、HP、MPのみマイナス
                int current_hp = _npc.getCurrentHp() - _hpConsume;
                _npc.setCurrentHp( current_hp );

                int current_mp = _npc.getCurrentMp() - _mpConsume;
                _npc.setCurrentMp( current_mp );
                return;
            }

            // HP・MPをマイナス
            if ( isHPMPConsume() )
            {
                if ( _skillId == L1SkillId.FINAL_BURN )
                { // ファイナル バーン
                    _player.setCurrentHp( 1 );
                    _player.setCurrentMp( 0 );
                }
                else
                {
                    int current_hp = _player.getCurrentHp() - _hpConsume;
                    _player.setCurrentHp( current_hp );

                    int current_mp = _player.getCurrentMp() - _mpConsume;
                    _player.setCurrentMp( current_mp );
                }
            }

            // Lawfulをマイナス
            int lawful = _player.getLawful() + _skill.getLawful();
            if ( lawful > 32767 )
            {
                lawful = 32767;
            }
            if ( lawful < -32767 )
            {
                lawful = -32767;
            }
            _player.setLawful( lawful );

            int itemConsume = _skill.getItemConsumeId();
            int itemConsumeCount = _skill.getItemConsumeCount();

            if ( itemConsume == 0 )
            {
                return; // 材料を必要としない魔法
            }

            // 使用材料をマイナス
            _player.getInventory().consumeItem( itemConsume, itemConsumeCount );
        }

        // マジックリストに追加する。
        private void addMagicList( L1Character cha, bool repetition )
        {
            if ( _skillTime == 0 )
            {
                _getBuffDuration = _skill.getBuffDuration() * 1000; // 効果時間
                if ( _skill.getBuffDuration() == 0 )
                {
                    if ( _skillId == L1SkillId.INVISIBILITY )
                    { // インビジビリティ
                        cha.setSkillEffect( L1SkillId.INVISIBILITY, 0 );
                    }
                    return;
                }
            }
            else
            {
                _getBuffDuration = _skillTime * 1000; // パラメータのtimeが0以外なら、効果時間として設定する
            }

            if ( _skillId == L1SkillId.SHOCK_STUN )
            {
                _getBuffDuration = _shockStunDuration;
            }

            if ( _skillId == L1SkillId.CURSE_POISON )
            { // カーズポイズンの効果処理はL1Poisonに移譲。
                return;
            }
            if ( _skillId == L1SkillId.CURSE_PARALYZE
                    || _skillId == L1SkillId.CURSE_PARALYZE2 )
            { // カーズパラライズの効果処理はL1CurseParalysisに移譲。
                return;
            }
            if ( _skillId == L1SkillId.SHAPE_CHANGE )
            { // シェイプチェンジの効果処理はL1PolyMorphに移譲。
                return;
            }
            if ( _skillId == L1SkillId.BLESSED_ARMOR || _skillId == L1SkillId.HOLY_WEAPON // 武器・防具に効果がある処理はL1ItemInstanceに移譲。
                    || _skillId == L1SkillId.ENCHANT_WEAPON || _skillId == L1SkillId.BLESS_WEAPON
                    || _skillId == L1SkillId.SHADOW_FANG )
            {
                return;
            }
            if ( ( _skillId == L1SkillId.ICE_LANCE || _skillId == L1SkillId.FREEZING_BLIZZARD
                    || _skillId == L1SkillId.FREEZING_BREATH ) && !_isFreeze )
            { // 凍結失敗
                return;
            }
            if ( _skillId == L1SkillId.AWAKEN_ANTHARAS || _skillId == L1SkillId.AWAKEN_FAFURION
                    || _skillId == L1SkillId.AWAKEN_VALAKAS )
            { // 覚醒の効果処理はL1Awakeに移譲。
                return;
            }

            cha.setSkillEffect( _skillId, _getBuffDuration );

            if ( cha is L1PcInstance && repetition )
            { // 対象がPCで既にスキルが重複している場合
                L1PcInstance pc = (L1PcInstance)cha;
                sendIcon( pc );
            }
        }

        // アイコンの送信
        private void sendIcon( L1PcInstance pc )
        {
            if ( _skillTime == 0 )
            {
                _getBuffIconDuration = _skill.getBuffDuration(); // 効果時間
            }
            else
            {
                _getBuffIconDuration = _skillTime; // パラメータのtimeが0以外なら、効果時間として設定する
            }

            if ( _skillId == L1SkillId.SHIELD )
            { // シールド
                pc.sendPackets( new S_SkillIconShield( 5, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.SHADOW_ARMOR )
            { // シャドウ アーマー
                pc.sendPackets( new S_SkillIconShield( 3, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.DRESS_DEXTERITY )
            { // ドレス デクスタリティー
                pc.sendPackets( new S_Dexup( pc, 2, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.DRESS_MIGHTY )
            { // ドレス マイティー
                pc.sendPackets( new S_Strup( pc, 2, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.GLOWING_AURA )
            { // グローウィング オーラ
                pc.sendPackets( new S_SkillIconAura( 113, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.SHINING_AURA )
            { // シャイニング オーラ
                pc.sendPackets( new S_SkillIconAura( 114, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.BRAVE_AURA )
            { // ブレイブ オーラ
                pc.sendPackets( new S_SkillIconAura( 116, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.FIRE_WEAPON )
            { // ファイアー ウェポン
                pc.sendPackets( new S_SkillIconAura( 147, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.WIND_SHOT )
            { // ウィンド ショット
                pc.sendPackets( new S_SkillIconAura( 148, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.FIRE_BLESS )
            { // ファイアー ブレス
                pc.sendPackets( new S_SkillIconAura( 154, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.STORM_EYE )
            { // ストーム アイ
                pc.sendPackets( new S_SkillIconAura( 155, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.EARTH_BLESS )
            { // アース ブレス
                pc.sendPackets( new S_SkillIconShield( 7, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.BURNING_WEAPON )
            { // バーニング ウェポン
                pc.sendPackets( new S_SkillIconAura( 162, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.STORM_SHOT )
            { // ストーム ショット
                pc.sendPackets( new S_SkillIconAura( 165, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.IRON_SKIN )
            { // アイアン スキン
                pc.sendPackets( new S_SkillIconShield( 10, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.EARTH_SKIN )
            { // アース スキン
                pc.sendPackets( new S_SkillIconShield( 6, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_STR )
            { // フィジカル エンチャント：STR
                pc.sendPackets( new S_Strup( pc, 5, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_DEX )
            { // フィジカル エンチャント：DEX
                pc.sendPackets( new S_Dexup( pc, 5, _getBuffIconDuration ) );
            }
            else if ( _skillId == L1SkillId.HASTE || _skillId == L1SkillId.GREATER_HASTE )
            { // グレーターヘイスト
                pc.sendPackets( new S_SkillHaste( pc.getId(), 1,
                        _getBuffIconDuration ) );
                pc.broadcastPacket( new S_SkillHaste( pc.getId(), 1, 0 ) );
            }
            else if ( _skillId == L1SkillId.HOLY_WALK
                  || _skillId == L1SkillId.MOVING_ACCELERATION || _skillId == L1SkillId.WIND_WALK )
            { // ホーリーウォーク、ムービングアクセレーション、ウィンドウォーク
                pc.sendPackets( new S_SkillBrave( pc.getId(), 4,
                        _getBuffIconDuration ) );
                pc.broadcastPacket( new S_SkillBrave( pc.getId(), 4, 0 ) );
            }
            else if ( _skillId == L1SkillId.BLOODLUST )
            { // ブラッドラスト
                pc.sendPackets( new S_SkillBrave( pc.getId(), 6,
                        _getBuffIconDuration ) );
                pc.broadcastPacket( new S_SkillBrave( pc.getId(), 6, 0 ) );
            }
            else if ( _skillId == L1SkillId.SLOW
                  || _skillId == L1SkillId.MASS_SLOW || _skillId == L1SkillId.ENTANGLE )
            { // スロー、エンタングル、マススロー
                pc.sendPackets( new S_SkillHaste( pc.getId(), 2,
                        _getBuffIconDuration ) );
                pc.broadcastPacket( new S_SkillHaste( pc.getId(), 2, 0 ) );
            }
            else if ( _skillId == L1SkillId.IMMUNE_TO_HARM )
            {
                pc.sendPackets( new S_SkillIconGFX( 40, _getBuffIconDuration ) );
            }
            pc.sendPackets( new S_OwnCharStatus( pc ) );
        }

        // グラフィックの送信
        private void sendGrfx( bool isSkillAction )
        {
            int actionId = _skill.getActionId();
            int castgfx = _skill.getCastGfx();
            if ( castgfx == 0 )
            {
                return; // 表示するグラフィックが無い
            }

            if ( _user is L1PcInstance )
            {
                if ( _skillId == L1SkillId.FIRE_WALL || _skillId == L1SkillId.LIFE_STREAM )
                {
                    L1PcInstance pc = (L1PcInstance)_user;
                    if ( _skillId == L1SkillId.FIRE_WALL )
                    {
                        pc.setHeading( pc.targetDirection( _targetX, _targetY ) );
                        pc.sendPackets( new S_ChangeHeading( pc ) );
                        pc.broadcastPacket( new S_ChangeHeading( pc ) );
                    }
                    S_DoActionGFX gfx = new S_DoActionGFX( pc.getId(), actionId );
                    pc.sendPackets( gfx );
                    pc.broadcastPacket( gfx );
                    return;
                }

                int targetid = _target.getId();

                if ( _skillId == L1SkillId.SHOCK_STUN )
                {
                    if ( _targetList.Count == 0 )
                    { // 失敗
                        return;
                    }
                    else
                    {
                        if ( _target is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)_target;
                            pc.sendPackets( new S_SkillSound( pc.getId(), 4434 ) );
                            pc.broadcastPacket( new S_SkillSound( pc.getId(), 4434 ) );
                        }
                        else if ( _target is L1NpcInstance )
                        {
                            _target.broadcastPacket( new S_SkillSound( _target
                                    .getId(), 4434 ) );
                        }
                        return;
                    }
                }

                if ( _skillId == L1SkillId.LIGHT )
                {
                    L1PcInstance pc = (L1PcInstance)_target;
                    pc.sendPackets( new S_Sound( 145 ) );
                }

                if ( _targetList.Count == 0 && !( _skill.getTarget().Equals( "none" ) ) )
                {
                    // ターゲット数が０で対象を指定するスキルの場合、魔法使用エフェクトだけ表示して終了
                    int tempchargfx = _player.getTempCharGfx();
                    if ( tempchargfx == 5727 || tempchargfx == 5730 )
                    { // シャドウ系変身のモーション対応
                        actionId = ActionCodes.ACTION_SkillBuff;
                    }
                    else if ( tempchargfx == 5733 || tempchargfx == 5736 )
                    {
                        actionId = ActionCodes.ACTION_Attack;
                    }
                    if ( isSkillAction )
                    {
                        S_DoActionGFX gfx = new S_DoActionGFX( _player.getId(),
                                actionId );
                        _player.sendPackets( gfx );
                        _player.broadcastPacket( gfx );
                    }
                    return;
                }

                if ( _skill.getTarget().Equals( "attack" ) && _skillId != 18 )
                {
                    if ( isPcSummonPet( _target ) )
                    { // 対象がPC、サモン、ペット
                        if ( _player.getZoneType() == 1
                                || _target.getZoneType() == 1 // 攻撃する側または攻撃される側がセーフティーゾーン
                                || _player.checkNonPvP( _player, _target ) )
                        { // Non-PvP設定
                            _player.sendPackets( new S_UseAttackSkill( _player, 0,
                                    castgfx, _targetX, _targetY, actionId ) ); // ターゲットへのモーションはなし
                            _player.broadcastPacket( new S_UseAttackSkill( _player,
                                    0, castgfx, _targetX, _targetY, actionId ) );
                            return;
                        }
                    }

                    if ( _skill.getArea() == 0 )
                    { // 単体攻撃魔法
                        _player.sendPackets( new S_UseAttackSkill( _player, targetid,
                                castgfx, _targetX, _targetY, actionId ) );
                        _player.broadcastPacket( new S_UseAttackSkill( _player,
                                targetid, castgfx, _targetX, _targetY, actionId ) );
                        _target.broadcastPacketExceptTargetSight( new S_DoActionGFX(
                                targetid, ActionCodes.ACTION_Damage ), _player );
                    }
                    else
                    { // 有方向範囲攻撃魔法
                        L1Character[] cha = new L1Character[_targetList.Count];
                        int i = 0;
                        foreach ( TargetStatus ts in _targetList )
                        {
                            cha[i] = ts.getTarget();
                            i++;
                        }
                        _player.sendPackets( new S_RangeSkill( _player, cha, castgfx,
                                actionId, S_RangeSkill.TYPE_DIR ) );
                        _player.broadcastPacket( new S_RangeSkill( _player, cha,
                                castgfx, actionId, S_RangeSkill.TYPE_DIR ) );
                    }
                }
                else if ( _skill.getTarget().Equals( "none" ) && _skill.getType() ==
                      L1Skills.TYPE_ATTACK )
                { // 無方向範囲攻撃魔法
                    L1Character[] cha = new L1Character[_targetList.Count];
                    int i = 0;
                    foreach ( TargetStatus ts in _targetList )
                    {
                        cha[i] = ts.getTarget();
                        cha[i].broadcastPacketExceptTargetSight( new S_DoActionGFX(
                                cha[i].getId(), ActionCodes.ACTION_Damage ),
                                        _player );
                        i++;
                    }
                    _player.sendPackets( new S_RangeSkill( _player, cha, castgfx,
                            actionId, S_RangeSkill.TYPE_NODIR ) );
                    _player.broadcastPacket( new S_RangeSkill( _player, cha,
                            castgfx, actionId, S_RangeSkill.TYPE_NODIR ) );
                }
                else
                { // 補助魔法
                    // テレポート、マステレ、テレポートトゥマザー以外
                    if ( _skillId != 5 && _skillId != 69 && _skillId != 131 )
                    {
                        // 魔法を使う動作のエフェクトは使用者だけ
                        if ( isSkillAction )
                        {
                            S_DoActionGFX gfx = new S_DoActionGFX( _player.getId(),
                                    _skill.getActionId() );
                            _player.sendPackets( gfx );
                            _player.broadcastPacket( gfx );
                        }
                        if ( _skillId == L1SkillId.COUNTER_MAGIC
                                || _skillId == L1SkillId.COUNTER_BARRIER
                                || _skillId == L1SkillId.COUNTER_MIRROR )
                        {
                            _player.sendPackets( new S_SkillSound( targetid,
                                    castgfx ) );
                        }
                        else if ( _skillId == L1SkillId.TRUE_TARGET )
                        { // トゥルーターゲットは個別処理で送信済
                            return;
                        }
                        else if ( _skillId == L1SkillId.AWAKEN_ANTHARAS // 覚醒：アンタラス
                              || _skillId == L1SkillId.AWAKEN_FAFURION // 覚醒：パプリオン
                              || _skillId == L1SkillId.AWAKEN_VALAKAS )
                        { // 覚醒：ヴァラカス
                            if ( _skillId == _player.getAwakeSkillId() )
                            { // 再詠唱なら解除でエフェクトなし
                                _player.sendPackets( new S_SkillSound( targetid, castgfx ) );
                                _player.broadcastPacket( new S_SkillSound( targetid, castgfx ) );
                            }
                            else
                            {
                                return;
                            }
                        }
                        else
                        {
                            _player.sendPackets( new S_SkillSound( targetid,
                                    castgfx ) );
                            _player.broadcastPacket( new S_SkillSound( targetid,
                                    castgfx ) );
                        }
                    }

                    // スキルのエフェクト表示はターゲット全員だが、あまり必要性がないので、ステータスのみ送信
                    foreach ( TargetStatus ts in _targetList )
                    {
                        L1Character cha = ts.getTarget();
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            pc.sendPackets( new S_OwnCharStatus( pc ) );
                        }
                    }
                }
            }
            else if ( _user is L1NpcInstance )
            { // NPCがスキルを使った場合
                int targetid = _target.getId();

                if ( _user is L1MerchantInstance )
                {
                    _user.broadcastPacket( new S_SkillSound( targetid, castgfx ) );
                    return;
                }

                if ( _targetList.Count == 0 && !( _skill.getTarget().Equals( "none" ) ) )
                {
                    // ターゲット数が０で対象を指定するスキルの場合、魔法使用エフェクトだけ表示して終了
                    S_DoActionGFX gfx = new S_DoActionGFX( _user.getId(), _skill.getActionId() );
                    _user.broadcastPacket( gfx );
                    return;
                }

                if ( _skill.getTarget().Equals( "attack" ) && _skillId != 18 )
                {
                    if ( _skill.getArea() == 0 )
                    { // 単体攻撃魔法
                        _user.broadcastPacket( new S_UseAttackSkill( _user, targetid,
                                castgfx, _targetX, _targetY, actionId ) );
                        _target.broadcastPacketExceptTargetSight( new S_DoActionGFX( targetid, ActionCodes.ACTION_Damage ), _user );
                    }
                    else
                    { // 有方向範囲攻撃魔法
                        L1Character[] cha = new L1Character[_targetList.Count];
                        int i = 0;
                        foreach ( TargetStatus ts in _targetList )
                        {
                            cha[i] = ts.getTarget();
                            cha[i].broadcastPacketExceptTargetSight(
                                    new S_DoActionGFX( cha[i].getId(), ActionCodes
                                            .ACTION_Damage ), _user );
                            i++;
                        }
                        _user.broadcastPacket( new S_RangeSkill( _user, cha,
                                castgfx, actionId, S_RangeSkill.TYPE_DIR ) );
                    }
                }
                else if ( _skill.getTarget().Equals( "none" ) && _skill.getType() ==
                      L1Skills.TYPE_ATTACK )
                { // 無方向範囲攻撃魔法
                    L1Character[] cha = new L1Character[_targetList.Count];
                    int i = 0;
                    foreach ( TargetStatus ts in _targetList )
                    {
                        cha[i] = ts.getTarget();
                        i++;
                    }
                    _user.broadcastPacket( new S_RangeSkill( _user, cha, castgfx,
                            actionId, S_RangeSkill.TYPE_NODIR ) );
                }
                else
                { // 補助魔法
                    // テレポート、マステレ、テレポートトゥマザー以外
                    if ( _skillId != 5 && _skillId != 69 && _skillId != 131 )
                    {
                        // 魔法を使う動作のエフェクトは使用者だけ
                        S_DoActionGFX gfx = new S_DoActionGFX( _user.getId(), _skill.getActionId() );
                        _user.broadcastPacket( gfx );
                        _user.broadcastPacket( new S_SkillSound( targetid, castgfx ) );
                    }
                }
            }
        }

        // 重複できないスキルの削除
        // 例：ファイア ウェポンとバーニングウェポンなど
        private void deleteRepeatedSkills( L1Character cha )
        {
            int[][] repeatedSkills = {
                // ホーリー ウェポン、エンチャント ウェポン、ブレス ウェポン, シャドウ ファング
                // これらはL1ItemInstanceで管理
                // { HOLY_WEAPON, ENCHANT_WEAPON, BLESS_WEAPON, SHADOW_FANG },
                // ファイアー ウェポン、ウィンド ショット、ファイアー ブレス、ストーム アイ、バーニング ウェポン、ストーム ショット
                new int[] { L1SkillId.FIRE_WEAPON, L1SkillId.WIND_SHOT, L1SkillId.FIRE_BLESS, L1SkillId.STORM_EYE, L1SkillId.BURNING_WEAPON, L1SkillId.STORM_SHOT },
                // シールド、シャドウ アーマー、アース スキン、アースブレス、アイアン スキン
                new int[] { L1SkillId.SHIELD, L1SkillId.SHADOW_ARMOR, L1SkillId.EARTH_SKIN, L1SkillId.EARTH_BLESS, L1SkillId.IRON_SKIN },
                // ホーリー ウォーク、ムービング アクセレーション、ウィンド ウォーク、BP、ワッフル、ユグドラの実、ブラッドラスト
                new int[] { L1SkillId.HOLY_WALK, L1SkillId.MOVING_ACCELERATION, L1SkillId.WIND_WALK, L1SkillId.STATUS_BRAVE, L1SkillId.STATUS_ELFBRAVE, L1SkillId.STATUS_RIBRAVE, L1SkillId.BLOODLUST },
                // ヘイスト、グレーター ヘイスト、GP
                new int[] { L1SkillId.HASTE, L1SkillId.GREATER_HASTE, L1SkillId.STATUS_HASTE },
                // フィジカル エンチャント：DEX、ドレス デクスタリティー
                new int[] { L1SkillId.PHYSICAL_ENCHANT_DEX, L1SkillId.DRESS_DEXTERITY },
                // フィジカル エンチャント：STR、ドレス マイティー
                new int[] { L1SkillId.PHYSICAL_ENCHANT_STR, L1SkillId.DRESS_MIGHTY },
                // グローウィングオーラ、シャイニングオーラ
                new int[] { L1SkillId.GLOWING_AURA, L1SkillId.SHINING_AURA } };

            foreach ( int[] skills in repeatedSkills )
            {
                foreach ( int id in skills )
                {
                    if ( id == _skillId )
                    {
                        stopSkillList( cha, skills );
                    }
                }
            }
        }

        // 重複しているスキルを一旦すべて削除
        private void stopSkillList( L1Character cha, int[] repeat_skill )
        {
            foreach ( int skillId in repeat_skill )
            {
                if ( skillId != _skillId )
                {
                    cha.removeSkillEffect( skillId );
                }
            }
        }

        // ディレイの設定
        private void setDelay()
        {
            if ( _skill.getReuseDelay() > 0 )
            {
                //L1SkillDelay.onSkillUse( _user, _skill.getReuseDelay() );
                _user.setSkillDelay( true );
                new Timer( new TimerCallback( SkillDelayTimerSub ), null, _skill.getReuseDelay(), Timeout.Infinite );
            }
        }

        public void SkillDelayTimerSub( object state )
        {
            ( (L1Character)state ).setSkillDelay( false );
        }

        private void runSkill()
        {

            if ( _skillId == L1SkillId.LIFE_STREAM )
            {
                L1EffectSpawn.getInstance().spawnEffect( 81169,
                        _skill.getBuffDuration() * 1000,
                        _targetX, _targetY, _user.getMapId() );
                return;
            }
            else if ( _skillId == L1SkillId.CUBE_IGNITION )
            {
                L1EffectSpawn.getInstance().spawnEffect( 80149,
                        _skill.getBuffDuration() * 1000,
                        _targetX, _targetY, _user.getMapId(),
                        (L1PcInstance)_user, _skillId );
                return;
            }
            else if ( _skillId == L1SkillId.CUBE_QUAKE )
            {
                L1EffectSpawn.getInstance().spawnEffect( 80150,
                        _skill.getBuffDuration() * 1000,
                        _targetX, _targetY, _user.getMapId(),
                        (L1PcInstance)_user, _skillId );
                return;
            }
            else if ( _skillId == L1SkillId.CUBE_SHOCK )
            {
                L1EffectSpawn.getInstance().spawnEffect( 80151,
                        _skill.getBuffDuration() * 1000,
                        _targetX, _targetY, _user.getMapId(),
                        (L1PcInstance)_user, _skillId );
                return;
            }
            else if ( _skillId == L1SkillId.CUBE_BALANCE )
            {
                L1EffectSpawn.getInstance().spawnEffect( 80152,
                        _skill.getBuffDuration() * 1000,
                        _targetX, _targetY, _user.getMapId(),
                        (L1PcInstance)_user, _skillId );
                return;
            }

            if ( _skillId == L1SkillId.FIRE_WALL )
            { // ファイアーウォール
                L1EffectSpawn.getInstance().doSpawnFireWall( _user, _targetX, _targetY );
                return;
            }

            // カウンターマジック有/無効の設定
            foreach ( int skillId in EXCEPT_COUNTER_MAGIC )
            {
                if ( _skillId == skillId )
                {
                    _isCounterMagic = false; // カウンターマジック無効
                    break;
                }
            }

            // NPCにショックスタンを使用させるとonActionでNullPointerExceptionが発生するため
            // とりあえずPCが使用した時のみ
            if ( _skillId == L1SkillId.SHOCK_STUN && _user is L1PcInstance )
            {
                _target.onAction( _player );
            }

            if ( !isTargetCalc( _target ) )
            {
                return;
            }


            //TargetStatus ts = null;
            L1Character cha = null;
            int dmg = 0;
            int drainMana = 0;
            int heal = 0;
            bool isSuccess = false;
            int undeadType = 0;

            //for (Iterator<TargetStatus> iter = _targetList.iterator(); iter.hasNext(); )
            foreach ( TargetStatus ts in _targetList )
            {
                //ts = null;
                cha = null;
                dmg = 0;
                heal = 0;
                isSuccess = false;
                undeadType = 0;

                //ts = iter.next();
                cha = ts.getTarget();

                if ( !ts.isCalc() || !isTargetCalc( cha ) )
                {
                    continue; // 計算する必要がない。
                }

                L1Magic _magic = new L1Magic( _user, cha );
                _magic.setLeverage( getLeverage() );

                if ( cha is L1MonsterInstance )
                { // アンデットの判定
                    undeadType = ( (L1MonsterInstance)cha ).getNpcTemplate().get_undead();
                }

                // 確率系スキルで失敗が確定している場合
                if ( ( _skill.getType() == L1Skills.TYPE_CURSE ||
                     _skill.getType() == L1Skills.TYPE_PROBABILITY )
                        && isTargetFailure( cha ) )
                {
                    _targetList.Remove( ts ); //iter.remove();
                    continue;
                }

                if ( cha is L1PcInstance )
                { // ターゲットがPCの場合のみアイコンは送信する。
                    if ( _skillTime == 0 )
                    {
                        _getBuffIconDuration = _skill.getBuffDuration(); // 効果時間
                    }
                    else
                    {
                        _getBuffIconDuration = _skillTime; // パラメータのtimeが0以外なら、効果時間として設定する
                    }
                }

                deleteRepeatedSkills( cha ); // 重複したスキルの削除

                if ( _skill.getType() == L1Skills.TYPE_ATTACK
                        && _user.getId() != cha.getId() )
                { // 攻撃系スキル＆ターゲットが使用者以外であること。
                    if ( isUseCounterMagic( cha ) )
                    { // カウンターマジックが発動した場合、リストから削除
                        _targetList.Remove( ts ); //iter.remove();
                        continue;
                    }
                    dmg = _magic.calcMagicDamage( _skillId );
                    cha.removeSkillEffect( L1SkillId.ERASE_MAGIC ); // イレースマジック中なら、攻撃魔法で解除
                }
                else if ( _skill.getType() == L1Skills.TYPE_CURSE
                      || _skill.getType() == L1Skills.TYPE_PROBABILITY )
                { // 確率系スキル
                    isSuccess = _magic.calcProbabilityMagic( _skillId );
                    if ( _skillId != L1SkillId.ERASE_MAGIC )
                    {
                        cha.removeSkillEffect( L1SkillId.ERASE_MAGIC ); // イレースマジック中なら、確率魔法で解除
                    }
                    if ( _skillId != L1SkillId.FOG_OF_SLEEPING )
                    {
                        cha.removeSkillEffect( L1SkillId.FOG_OF_SLEEPING ); // フォグオブスリーピング中なら、確率魔法で解除
                    }
                    if ( isSuccess )
                    { // 成功したがカウンターマジックが発動した場合、リストから削除
                        if ( isUseCounterMagic( cha ) )
                        { // カウンターマジックが発動したか
                            _targetList.Remove( ts ); //iter.remove();
                            continue;
                        }
                    }
                    else
                    { // 失敗した場合、リストから削除
                        if ( _skillId == L1SkillId.FOG_OF_SLEEPING
                                && cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            pc.sendPackets( new S_ServerMessage( 297 ) ); // 軽いめまいを覚えました。
                        }
                        _targetList.Remove( ts ); //iter.remove();
                        continue;
                    }
                }
                else if ( _skill.getType() == L1Skills.TYPE_HEAL )
                { // 回復系スキル
                    // 回復量はマイナスダメージで表現
                    dmg = -1 * _magic.calcHealing( _skillId );
                    if ( cha.hasSkillEffect( L1SkillId.WATER_LIFE ) )
                    { // ウォーターライフ中は回復量２倍
                        dmg *= 2;
                    }
                    if ( cha.hasSkillEffect( L1SkillId.POLLUTE_WATER ) )
                    { // ポルートウォーター中は回復量1/2倍
                        dmg /= 2;
                    }
                }

                // ■■■■ 個別処理のあるスキルのみ書いてください。 ■■■■

                // すでにスキルを使用済みの場合なにもしない
                // ただしショックスタンは重ねがけ出来るため例外
                if ( cha.hasSkillEffect( _skillId ) && _skillId != L1SkillId.SHOCK_STUN )
                {
                    addMagicList( cha, true ); // ターゲットに魔法の効果時間を上書き
                    if ( _skillId != L1SkillId.SHAPE_CHANGE )
                    { // シェイプ チェンジは変身を上書き出来るため例外
                        continue;
                    }
                }

                // ●●●● PC、NPC両方効果のあるスキル ●●●●
                if ( _skillId == L1SkillId.HASTE )
                { // ヘイスト
                    if ( cha.getMoveSpeed() != 2 )
                    { // スロー中以外
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            if ( pc.getHasteItemEquipped() > 0 )
                            {
                                continue;
                            }
                            pc.setDrink( false );
                            pc.sendPackets( new S_SkillHaste( pc.getId(), 1, _getBuffIconDuration ) );
                        }
                        cha.broadcastPacket( new S_SkillHaste( cha.getId(), 1, 0 ) );
                        cha.setMoveSpeed( 1 );
                    }
                    else
                    { // スロー中
                        int skillNum = 0;
                        if ( cha.hasSkillEffect( L1SkillId.SLOW ) )
                        {
                            skillNum = L1SkillId.SLOW;
                        }
                        else if ( cha.hasSkillEffect( L1SkillId.MASS_SLOW ) )
                        {
                            skillNum = L1SkillId.MASS_SLOW;
                        }
                        else if ( cha.hasSkillEffect( L1SkillId.ENTANGLE ) )
                        {
                            skillNum = L1SkillId.ENTANGLE;
                        }
                        if ( skillNum != 0 )
                        {
                            cha.removeSkillEffect( skillNum );
                            cha.removeSkillEffect( L1SkillId.HASTE );
                            cha.setMoveSpeed( 0 );
                            continue;
                        }
                    }
                }
                else if ( _skillId == L1SkillId.CURE_POISON )
                {
                    cha.curePoison();
                }
                else if ( _skillId == L1SkillId.REMOVE_CURSE )
                {
                    cha.curePoison();
                    if ( cha.hasSkillEffect( L1SkillId.STATUS_CURSE_PARALYZING )
                     || cha.hasSkillEffect( L1SkillId.STATUS_CURSE_PARALYZED ) )
                    {
                        cha.cureParalaysis();
                    }
                }
                else if ( _skillId == L1SkillId.RESURRECTION
                      || _skillId == L1SkillId.GREATER_RESURRECTION )
                { // リザレクション、グレーターリザレクション
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( _player.getId() != pc.getId() )
                        {
                            if ( L1World.getInstance().getVisiblePlayer( pc, 0 ).Count > 0 )
                            {
                                foreach ( L1PcInstance visiblePc in L1World.getInstance().getVisiblePlayer( pc, 0 ) )
                                {
                                    if ( !visiblePc.isDead() )
                                    {
                                        // \f1その場所に他の人が立っているので復活させることができません。
                                        _player.sendPackets( new S_ServerMessage( 592 ) );
                                        return;
                                    }
                                }
                            }
                            if ( pc.getCurrentHp() == 0 && pc.isDead() )
                            {
                                if ( pc.getMap().isUseResurrection() )
                                {
                                    if ( _skillId == L1SkillId.RESURRECTION )
                                    {
                                        pc.setGres( false );
                                    }
                                    else if ( _skillId == L1SkillId.GREATER_RESURRECTION )
                                    {
                                        pc.setGres( true );
                                    }
                                    pc.setTempID( _player.getId() );
                                    pc.sendPackets( new S_Message_YN( 322, "" ) ); // また復活したいですか？（Y/N）
                                }
                            }
                        }
                    }
                    if ( cha is L1NpcInstance )
                    {
                        if ( !( cha is L1TowerInstance ) )
                        {
                            L1NpcInstance npc = (L1NpcInstance)cha;
                            if ( npc.getNpcTemplate().isCantResurrect() && !( npc is L1PetInstance ) )
                            {
                                return;
                            }
                            if ( npc is L1PetInstance && L1World.getInstance().getVisiblePlayer( npc, 0 ).Count > 0 )
                            {
                                foreach ( L1PcInstance visiblePc in L1World.getInstance().getVisiblePlayer( npc, 0 ) )
                                {
                                    if ( !visiblePc.isDead() )
                                    {
                                        // \f1その場所に他の人が立っているので復活させることができません。
                                        _player.sendPackets( new S_ServerMessage( 592 ) );
                                        return;
                                    }
                                }
                            }
                            if ( npc.getCurrentHp() == 0 && npc.isDead() )
                            {
                                npc.resurrect( npc.getMaxHp() / 4 );
                                npc.setResurrect( true );
                            }
                        }
                    }
                }
                else if ( _skillId == L1SkillId.CALL_OF_NATURE )
                { // コール オブ ネイチャー
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( _player.getId() != pc.getId() )
                        {
                            if ( L1World.getInstance().getVisiblePlayer( pc,
                                    0 ).Count > 0 )
                            {
                                foreach ( L1PcInstance visiblePc in L1World.getInstance().getVisiblePlayer( pc, 0 ) )
                                {
                                    if ( !visiblePc.isDead() )
                                    {
                                        // \f1その場所に他の人が立っているので復活させることができません。
                                        _player.sendPackets( new S_ServerMessage( 592 ) );
                                        return;
                                    }
                                }
                            }
                            if ( pc.getCurrentHp() == 0 && pc.isDead() )
                            {
                                pc.setTempID( _player.getId() );
                                pc.sendPackets( new S_Message_YN( 322, "" ) ); // また復活したいですか？（Y/N）
                            }
                        }
                    }
                    if ( cha is L1NpcInstance )
                    {
                        if ( !( cha is L1TowerInstance ) )
                        {
                            L1NpcInstance npc = (L1NpcInstance)cha;
                            if ( npc.getNpcTemplate().isCantResurrect()
                                    && !( npc is L1PetInstance ) )
                            {
                                return;
                            }
                            if ( npc is L1PetInstance
                                    && L1World.getInstance()
                                            .getVisiblePlayer( npc, 0 )
                                            .Count > 0 )
                            {
                                foreach ( L1PcInstance visiblePc in L1World
                                        .getInstance().getVisiblePlayer( npc,
                                                0 ) )
                                {
                                    if ( !visiblePc.isDead() )
                                    {
                                        // \f1その場所に他の人が立っているので復活させることができません。
                                        _player.sendPackets( new S_ServerMessage(
                                                592 ) );
                                        return;
                                    }
                                }
                            }
                            if ( npc.getCurrentHp() == 0 && npc.isDead() )
                            {
                                npc.resurrect( cha.getMaxHp() );// HPを全回復する
                                npc.resurrect( cha.getMaxMp() / 100 );// MPを0にする
                                npc.setResurrect( true );
                            }
                        }
                    }
                }
                else if ( _skillId == L1SkillId.DETECTION )
                { // ディテクション
                    if ( cha is L1NpcInstance )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        int hiddenStatus = npc.getHiddenStatus();
                        if ( hiddenStatus == L1NpcInstance.HIDDEN_STATUS_SINK )
                        {
                            npc.appearOnGround( _player );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.COUNTER_DETECTION )
                { // カウンターディテクション
                    if ( cha is L1PcInstance )
                    {
                        dmg = _magic.calcMagicDamage( _skillId );
                    }
                    else if ( cha is L1NpcInstance )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        int hiddenStatus = npc.getHiddenStatus();
                        if ( hiddenStatus == L1NpcInstance.HIDDEN_STATUS_SINK )
                        {
                            npc.appearOnGround( _player );
                        }
                        else
                        {
                            dmg = 0;
                        }
                    }
                    else
                    {
                        dmg = 0;
                    }
                }
                else if ( _skillId == L1SkillId.TRUE_TARGET )
                { // トゥルーターゲット
                    if ( _user is L1PcInstance )
                    {
                        L1PcInstance pri = (L1PcInstance)_user;
                        pri.sendPackets( new S_TrueTarget( _targetID,
                                pri.getId(), _message ) );
                        L1PcInstance[] players = L1World.getInstance().getClan( pri.getClanname() ).getOnlineClanMember();
                        foreach ( L1PcInstance pc in players )
                        {
                            pc.sendPackets( new S_TrueTarget( _targetID, pc.getId(), _message ) );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.ELEMENTAL_FALL_DOWN )
                { // エレメンタルフォールダウン
                    if ( _user is L1PcInstance )
                    {
                        int playerAttr = _player.getElfAttr();
                        int i = -50;
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            switch ( playerAttr )
                            {
                                case 0:
                                    _player.sendPackets( new S_ServerMessage( 79 ) );
                                    break;
                                case 1:
                                    pc.addEarth( i );
                                    pc.setAddAttrKind( 1 );
                                    break;
                                case 2:
                                    pc.addFire( i );
                                    pc.setAddAttrKind( 2 );
                                    break;
                                case 4:
                                    pc.addWater( i );
                                    pc.setAddAttrKind( 4 );
                                    break;
                                case 8:
                                    pc.addWind( i );
                                    pc.setAddAttrKind( 8 );
                                    break;
                                default:
                                    break;
                            }
                        }
                        else if ( cha is L1MonsterInstance )
                        {
                            L1MonsterInstance mob = (L1MonsterInstance)cha;
                            switch ( playerAttr )
                            {
                                case 0:
                                    _player.sendPackets( new S_ServerMessage( 79 ) );
                                    break;
                                case 1:
                                    mob.addEarth( i );
                                    mob.setAddAttrKind( 1 );
                                    break;
                                case 2:
                                    mob.addFire( i );
                                    mob.setAddAttrKind( 2 );
                                    break;
                                case 4:
                                    mob.addWater( i );
                                    mob.setAddAttrKind( 4 );
                                    break;
                                case 8:
                                    mob.addWind( i );
                                    mob.setAddAttrKind( 8 );
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                // ★★★ 回復系スキル ★★★
                else if ( ( _skillId == L1SkillId.HEAL || _skillId == L1SkillId.EXTRA_HEAL
                        || _skillId == L1SkillId.GREATER_HEAL || _skillId == L1SkillId.FULL_HEAL
                        || _skillId == L1SkillId.HEAL_ALL || _skillId == L1SkillId.NATURES_TOUCH
                        || _skillId == L1SkillId.NATURES_BLESSING )
                        && ( _user is L1PcInstance ) )
                {
                    cha.removeSkillEffect( L1SkillId.WATER_LIFE );
                }
                // ★★★ 攻撃系スキル ★★★
                // チルタッチ、バンパイアリックタッチ
                else if ( _skillId == L1SkillId.CHILL_TOUCH || _skillId == L1SkillId.VAMPIRIC_TOUCH )
                {
                    heal = dmg;
                }
                else if ( _skillId == L1SkillId.TRIPLE_ARROW )
                { // トリプルアロー
                    // 1回射出する毎にアロー、ダメージ、命中を計算する
                    // アローが残り1でサイハの弓を持ってるとき、
                    // 最初は普通の攻撃その後は魔法攻撃
                    // アローが残り1で普通の弓を持ってるとき，最初は普通の攻撃，
                    // その後はアローの射出を行わず動きだけを行う。

                    // GFX Check (Made by HuntBoy)
                    bool gfxcheck = false;
                    int[] BowGFX = { 138, 37, 3860, 3126, 3420, 2284, 3105,
							3145, 3148, 3151, 3871, 4125, 2323, 3892, 3895,
							3898, 3901, 4917, 4918, 4919, 4950, 6087, 6140,
							6145, 6150, 6155, 6160, 6269, 6272, 6275, 6278,
							6826, 6827, 6836, 6837, 6846, 6847, 6856, 6857,
							6866, 6867, 6876, 6877, 6886, 6887 };
                    int playerGFX = _player.getTempCharGfx();
                    foreach ( int gfx in BowGFX )
                    {
                        if ( playerGFX == gfx )
                        {
                            gfxcheck = true;
                            break;
                        }
                    }
                    if ( !gfxcheck )
                    {
                        return;
                    }

                    for ( int i = 3; i > 0; i-- )
                    {
                        _target.onAction( _player );
                    }
                    _player.sendPackets( new S_SkillSound( _player.getId(),
                            4394 ) );
                    _player.broadcastPacket( new S_SkillSound( _player.getId(),
                            4394 ) );
                }
                else if ( _skillId == L1SkillId.FOE_SLAYER )
                { // フォースレイヤー
                    for ( int i = 3; i > 0; i-- )
                    {
                        _target.onAction( _player );
                    }
                    _player.sendPackets( new S_SkillSound( _target.getId(),
                            6509 ) );
                    _player.sendPackets( new S_SkillSound( _player.getId(),
                            7020 ) );
                    _player.broadcastPacket( new S_SkillSound( _target.getId(),
                            6509 ) );
                    _player.broadcastPacket( new S_SkillSound( _player.getId(),
                            7020 ) );
                }
                else if ( _skillId == 10026 || _skillId == 10027
                      || _skillId == 10028 || _skillId == 10029 )
                { // 安息攻撃
                    if ( _user is L1NpcInstance )
                    {
                        _user.broadcastPacket( new S_NpcChatPacket( _npc, "$3717", 0 ) ); // さあ、おまえに安息を与えよう。
                    }
                    else
                    {
                        _player.broadcastPacket( new S_ChatPacket( _player, "$3717", 0, 0 ) ); // さあ、おまえに安息を与えよう。
                    }
                }
                else if ( _skillId == 10057 )
                { // 引き寄せ
                    L1Teleport.teleportToTargetFront( cha, _user, 1 );
                }

              // ★★★ 確率系スキル ★★★
                else if ( _skillId == L1SkillId.SLOW
                        || _skillId == L1SkillId.MASS_SLOW || _skillId == L1SkillId.ENTANGLE )
                { // スロー、マス
                    // スロー、エンタングル
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( pc.getHasteItemEquipped() > 0 )
                        {
                            continue;
                        }
                    }
                    if ( cha.getMoveSpeed() == 0 )
                    {
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            pc.sendPackets( new S_SkillHaste( pc.getId(), 2,
                                    _getBuffIconDuration ) );
                        }
                        cha.broadcastPacket( new S_SkillHaste( cha.getId(),
                                2, _getBuffIconDuration ) );
                        cha.setMoveSpeed( 2 );
                    }
                    else if ( cha.getMoveSpeed() == 1 )
                    {
                        int skillNum = 0;
                        if ( cha.hasSkillEffect( L1SkillId.HASTE ) )
                        {
                            skillNum = L1SkillId.HASTE;
                        }
                        else if ( cha.hasSkillEffect( L1SkillId.GREATER_HASTE ) )
                        {
                            skillNum = L1SkillId.GREATER_HASTE;
                        }
                        else if ( cha.hasSkillEffect( L1SkillId.STATUS_HASTE ) )
                        {
                            skillNum = L1SkillId.STATUS_HASTE;
                        }
                        if ( skillNum != 0 )
                        {
                            cha.removeSkillEffect( skillNum );
                            cha.removeSkillEffect( _skillId );
                            cha.setMoveSpeed( 0 );
                            continue;
                        }
                    }
                }
                else if ( _skillId == L1SkillId.CURSE_BLIND || _skillId == L1SkillId.DARKNESS )
                {
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( pc.hasSkillEffect( L1SkillId.STATUS_FLOATING_EYE ) )
                        {
                            pc.sendPackets( new S_CurseBlind( 2 ) );
                        }
                        else
                        {
                            pc.sendPackets( new S_CurseBlind( 1 ) );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.CURSE_POISON )
                {
                    L1DamagePoison.doInfection( _user, cha, 3000, 5 );
                }
                else if ( _skillId == L1SkillId.CURSE_PARALYZE
                      || _skillId == L1SkillId.CURSE_PARALYZE2 )
                {
                    if ( !cha.hasSkillEffect( L1SkillId.EARTH_BIND )
                            && !cha.hasSkillEffect( L1SkillId.ICE_LANCE )
                            && !cha.hasSkillEffect( L1SkillId.FREEZING_BLIZZARD )
                            && !cha.hasSkillEffect( L1SkillId.FREEZING_BREATH ) )
                    {
                        if ( cha is L1PcInstance )
                        {
                            L1CurseParalysis.curse( cha, 8000, 16000 );
                        }
                        else if ( cha is L1MonsterInstance )
                        {
                            L1CurseParalysis.curse( cha, 0, 16000 );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.WEAKNESS )
                { // ウィークネス
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( -5 );
                        pc.addHitup( -1 );
                    }
                }
                else if ( _skillId == L1SkillId.DISEASE )
                { // ディジーズ
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( -6 );
                        pc.addAc( 12 );
                    }
                }
                else if ( _skillId == L1SkillId.ICE_LANCE // アイスランス
                      || _skillId == L1SkillId.FREEZING_BLIZZARD // フリージングブリザード
                      || _skillId == L1SkillId.FREEZING_BREATH )
                { // フリージングブレス
                    _isFreeze = _magic.calcProbabilityMagic( _skillId );
                    if ( _isFreeze )
                    {
                        int time = _skill.getBuffDuration() * 1000;
                        L1EffectSpawn.getInstance()
                                .spawnEffect( 81168, time,
                                        cha.getX(), cha.getY(), cha.getMapId() );
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            pc.sendPackets( new S_Poison( pc.getId(), 2 ) );
                            pc.broadcastPacket( new S_Poison( pc.getId(), 2 ) );
                            pc.sendPackets( new S_Paralysis(
                                    S_Paralysis.TYPE_FREEZE, true ) );
                        }
                        else if ( cha is L1MonsterInstance
                              || cha is L1SummonInstance
                              || cha is L1PetInstance )
                        {
                            L1NpcInstance npc = (L1NpcInstance)cha;
                            npc.broadcastPacket( new S_Poison( npc.getId(), 2 ) );
                            npc.setParalyzed( true );
                            npc.setParalysisTime( time );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.EARTH_BIND )
                { // アースバインド
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_Poison( pc.getId(), 2 ) );
                        pc.broadcastPacket( new S_Poison( pc.getId(), 2 ) );
                        pc.sendPackets( new S_Paralysis(
                                S_Paralysis.TYPE_FREEZE, true ) );
                    }
                    else if ( cha is L1MonsterInstance
                          || cha is L1SummonInstance
                          || cha is L1PetInstance )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        npc.broadcastPacket( new S_Poison( npc.getId(), 2 ) );
                        npc.setParalyzed( true );
                        npc.setParalysisTime( _skill.getBuffDuration() * 1000 );
                    }
                }
                else if ( _skillId == L1SkillId.SHOCK_STUN )
                {
                    int[] stunTimeArray = { 500, 1000, 1500, 2000, 2500, 3000 };
                    Random random = new Random();
                    int rnd = random.Next( stunTimeArray.Length );
                    _shockStunDuration = stunTimeArray[rnd];
                    if ( cha is L1PcInstance
                            && cha.hasSkillEffect( L1SkillId.SHOCK_STUN ) )
                    {
                        _shockStunDuration += cha
                                .getSkillEffectTimeSec( L1SkillId.SHOCK_STUN ) * 1000;
                    }

                    L1EffectSpawn.getInstance()
                            .spawnEffect( 81162, _shockStunDuration,
                                    cha.getX(), cha.getY(), cha.getMapId() );
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_Paralysis( S_Paralysis.TYPE_STUN,
                                true ) );
                    }
                    else if ( cha is L1MonsterInstance
                          || cha is L1SummonInstance
                          || cha is L1PetInstance )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        npc.setParalyzed( true );
                        npc.setParalysisTime( _shockStunDuration );
                    }
                }
                else if ( _skillId == L1SkillId.WIND_SHACKLE )
                { // ウィンド シャックル
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_SkillIconWindShackle( pc.getId(),
                                _getBuffIconDuration ) );
                    }
                }
                else if ( _skillId == L1SkillId.CANCELLATION )
                {
                    if ( cha is L1NpcInstance )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        int npcId = npc.getNpcTemplate().get_npcId();
                        if ( npcId == 71092 )
                        { // 調査員
                            if ( npc.getGfxId() == npc.getTempCharGfx() )
                            {
                                npc.setTempCharGfx( 1314 );
                                npc.broadcastPacket( new S_ChangeShape( npc
                                        .getId(), 1314 ) );
                                return;
                            }
                            else
                            {
                                return;
                            }
                        }
                        if ( npcId == 45640 )
                        { // ユニコーン
                            if ( npc.getGfxId() == npc.getTempCharGfx() )
                            {
                                npc.setCurrentHp( npc.getMaxHp() );
                                npc.setTempCharGfx( 2332 );
                                npc.broadcastPacket( new S_ChangeShape( npc
                                        .getId(), 2332 ) );
                                npc.setName( "$2103" );
                                npc.setNameId( "$2103" );
                                npc.broadcastPacket( new S_ChangeName( npc
                                        .getId(), "$2103" ) );
                            }
                            else if ( npc.getTempCharGfx() == 2332 )
                            {
                                npc.setCurrentHp( npc.getMaxHp() );
                                npc.setTempCharGfx( 2755 );
                                npc.broadcastPacket( new S_ChangeShape( npc
                                        .getId(), 2755 ) );
                                npc.setName( "$2488" );
                                npc.setNameId( "$2488" );
                                npc.broadcastPacket( new S_ChangeName( npc
                                        .getId(), "$2488" ) );
                            }
                        }
                        if ( npcId == 81209 )
                        { // ロイ
                            if ( npc.getGfxId() == npc.getTempCharGfx() )
                            {
                                npc.setTempCharGfx( 4310 );
                                npc.broadcastPacket( new S_ChangeShape( npc
                                        .getId(), 4310 ) );
                                return;
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                    if ( _player != null && _player.isInvisble() )
                    {
                        _player.delInvis();
                    }
                    if ( !( cha is L1PcInstance ) )
                    {
                        L1NpcInstance npc = (L1NpcInstance)cha;
                        npc.setMoveSpeed( 0 );
                        npc.setBraveSpeed( 0 );
                        npc.broadcastPacket( new S_SkillHaste( cha.getId(), 0,
                                0 ) );
                        npc.broadcastPacket( new S_SkillBrave( cha.getId(), 0,
                                0 ) );
                        npc.setWeaponBreaked( false );
                        npc.setParalyzed( false );
                        npc.setParalysisTime( 0 );
                    }

                    // スキルの解除
                    for ( int skillNum = L1SkillId.SKILLS_BEGIN; skillNum <= L1SkillId.SKILLS_END; skillNum++ )
                    {
                        if ( isNotCancelable( skillNum ) && !cha.isDead() )
                        {
                            continue;
                        }
                        cha.removeSkillEffect( skillNum );
                    }

                    // ステータス強化、異常の解除
                    cha.curePoison();
                    cha.cureParalaysis();
                    for ( int skillNum = L1SkillId.STATUS_BEGIN; skillNum <= L1SkillId.STATUS_END; skillNum++ )
                    {
                        if ( skillNum == L1SkillId.STATUS_CHAT_PROHIBITED // チャット禁止は解除しない
                                || skillNum == L1SkillId.STATUS_CURSE_BARLOG // バルログの呪いは解除しない
                                || skillNum == L1SkillId.STATUS_CURSE_YAHEE )
                        { // ヤヒの呪いは解除しない
                            continue;
                        }
                        cha.removeSkillEffect( skillNum );
                    }

                    if ( cha is L1PcInstance )
                    {
                    }

                    // 料理の解除
                    for ( int skillNum = L1SkillId.COOKING_BEGIN; skillNum <= L1SkillId.COOKING_END; skillNum++ )
                    {
                        if ( isNotCancelable( skillNum ) )
                        {
                            continue;
                        }
                        cha.removeSkillEffect( skillNum );
                    }

                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;

                        // アイテム装備による変身の解除
                        L1PolyMorph.undoPoly( pc );
                        pc.sendPackets( new S_CharVisualUpdate( pc ) );
                        pc.broadcastPacket( new S_CharVisualUpdate( pc ) );

                        // ヘイストアイテム装備時はヘイスト関連のスキルが何も掛かっていないはずなのでここで解除
                        if ( pc.getHasteItemEquipped() > 0 )
                        {
                            pc.setMoveSpeed( 0 );
                            pc.sendPackets( new S_SkillHaste( pc.getId(), 0, 0 ) );
                            pc.broadcastPacket( new S_SkillHaste( pc.getId(), 0,
                                    0 ) );
                        }
                    }
                    cha.removeSkillEffect( L1SkillId.STATUS_FREEZE ); // Freeze解除
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_CharVisualUpdate( pc ) );
                        pc.broadcastPacket( new S_CharVisualUpdate( pc ) );
                        if ( pc.isPrivateShop() )
                        {
                            pc.sendPackets( new S_DoActionShop( pc.getId(),
                                    ActionCodes.ACTION_Shop, pc.getShopChat() ) );
                            pc.broadcastPacket( new S_DoActionShop( pc.getId(),
                                    ActionCodes.ACTION_Shop, pc.getShopChat() ) );
                        }
                        if ( _user is L1PcInstance )
                        {
                            L1PinkName.onAction( pc, _user );
                        }
                    }
                }
                else if ( _skillId == L1SkillId.TURN_UNDEAD // ターン アンデッド
                      && ( undeadType == 1 || undeadType == 3 ) )
                {
                    // ダメージを対象のHPとする。
                    dmg = cha.getCurrentHp();
                }
                else if ( _skillId == L1SkillId.MANA_DRAIN )
                { // マナ ドレイン
                    Random random = new Random();
                    int chance = random.Next( 10 ) + 5;
                    drainMana = chance + ( _user.getInt() / 2 );
                    if ( cha.getCurrentMp() < drainMana )
                    {
                        drainMana = cha.getCurrentMp();
                    }
                }
                else if ( _skillId == L1SkillId.WEAPON_BREAK )
                { // ウェポン ブレイク
                    /*
                     * 対NPCの場合、L1Magicのダメージ算出でダメージ1/2としているので
                     * こちらには、対PCの場合しか記入しない。 損傷量は1~(int/3)まで
                     */
                    if ( _calcType == PC_PC || _calcType == NPC_PC )
                    {
                        if ( cha is L1PcInstance )
                        {
                            L1PcInstance pc = (L1PcInstance)cha;
                            L1ItemInstance weapon = pc.getWeapon();
                            if ( weapon != null )
                            {
                                Random random = new Random();
                                int weaponDamage = random.Next( _user
                                        .getInt() / 3 ) + 1;
                                // \f1あなたの%0が損傷しました。
                                pc.sendPackets( new S_ServerMessage( 268, weapon
                                        .getLogName() ) );
                                pc.getInventory().receiveDamage( weapon,
                                        weaponDamage );
                            }
                        }
                    }
                    else
                    {
                        ( (L1NpcInstance)cha ).setWeaponBreaked( true );
                    }
                }
                else if ( _skillId == L1SkillId.FOG_OF_SLEEPING )
                {
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_Paralysis( S_Paralysis.TYPE_SLEEP,
                                true ) );
                    }
                    cha.setSleeped( true );
                }
                else if ( _skillId == L1SkillId.STATUS_FREEZE )
                { // Freeze
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_Paralysis( S_Paralysis.TYPE_BIND,
                                true ) );
                    }
                }
                else if ( _skillId == L1SkillId.GUARD_BRAKE )
                { // ガードブレイク
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( 15 );
                    }
                }
                else if ( _skillId == L1SkillId.HORROR_OF_DEATH )
                { // ホラーオブデス
                    if ( cha is L1PcInstance )
                    {
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addStr( -5 );
                        pc.addInt( -5 );
                    }
                }

                // ●●●● PCにしか効果のないスキル ●●●●
                if ( _calcType == PC_PC || _calcType == NPC_PC )
                {
                    // ★★★ 特殊系スキル★★★
                    if ( _skillId == L1SkillId.TELEPORT || _skillId == L1SkillId.MASS_TELEPORT )
                    { // マステレ、テレポート
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1BookMark bookm = pc.getBookMark( _bookmarkId );
                        if ( bookm != null )
                        { // ブックマークを取得出来たらテレポート
                            if ( pc.getMap().isEscapable() || pc.isGm() )
                            {
                                int newX = bookm.getLocX();
                                int newY = bookm.getLocY();
                                short mapId = bookm.getMapId();

                                if ( _skillId == L1SkillId.MASS_TELEPORT )
                                { // マステレポート
                                    List<L1PcInstance> clanMember = L1World
                                            .getInstance().getVisiblePlayer( pc );
                                    foreach ( L1PcInstance member in clanMember )
                                    {
                                        if ( pc.getLocation()
                                                .getTileLineDistance(
                                                        member.getLocation() ) <= 3
                                                && member.getClanid() == pc
                                                        .getClanid()
                                                && pc.getClanid() != 0
                                                && member.getId() != pc.getId() )
                                        {
                                            L1Teleport.teleport( member, newX,
                                                    newY, mapId, 5, true );
                                        }
                                    }
                                }
                                L1Teleport.teleport( pc, newX, newY, mapId, 5,
                                        true );
                            }
                            else
                            { // テレポート不可マップへの移動制限
                                L1Teleport.teleport( pc, pc.getX(), pc.getY(),
                                        pc.getMapId(), pc.getHeading(), false );
                                pc.sendPackets( new S_ServerMessage( 79 ) );
                            }
                        }
                        else
                        { // ブックマークが取得出来なかった、あるいは「任意の場所」を選択した場合の処理
                            if ( pc.getMap().isTeleportable() || pc.isGm() )
                            {
                                L1Location newLocation = pc.getLocation()
                                        .randomLocation( 200, true );
                                int newX = newLocation.getX();
                                int newY = newLocation.getY();
                                short mapId = (short)newLocation.getMapId();

                                if ( _skillId == L1SkillId.MASS_TELEPORT )
                                { // マステレポート
                                    List<L1PcInstance> clanMember = L1World
                                            .getInstance().getVisiblePlayer( pc );
                                    foreach ( L1PcInstance member in clanMember )
                                    {
                                        if ( pc.getLocation()
                                                .getTileLineDistance(
                                                        member.getLocation() ) <= 3
                                                && member.getClanid() == pc
                                                        .getClanid()
                                                && pc.getClanid() != 0
                                                && member.getId() != pc.getId() )
                                        {
                                            L1Teleport.teleport( member, newX,
                                                    newY, mapId, 5, true );
                                        }
                                    }
                                }
                                L1Teleport.teleport( pc, newX, newY, mapId, 5,
                                        true );
                            }
                            else
                            {
                                pc.sendPackets( new S_ServerMessage( 276 ) );
                                L1Teleport.teleport( pc, pc.getX(), pc.getY(),
                                        pc.getMapId(), pc.getHeading(), false );
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.TELEPORT_TO_MATHER )
                    { // テレポート トゥ
                        // マザー
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( pc.getMap().isEscapable() || pc.isGm() )
                        {
                            L1Teleport.teleport( pc, 33051, 32337, (short)4, 5,
                                    true );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 647 ) );
                            L1Teleport.teleport( pc, pc.getX(), pc.getY(), pc
                                    .getMapId(), pc.getHeading(), false );
                        }
                    }
                    else if ( _skillId == L1SkillId.CALL_CLAN )
                    { // コールクラン
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1PcInstance clanPc = (L1PcInstance)L1World
                                .getInstance().findObject( _targetID );
                        if ( clanPc != null )
                        {
                            clanPc.setTempID( pc.getId() ); // 相手のオブジェクトIDを保存しておく
                            clanPc.sendPackets( new S_Message_YN( 729, "" ) ); // 君主が呼んでいます。召喚に応じますか？（Y/N）
                        }
                    }
                    else if ( _skillId == L1SkillId.RUN_CLAN )
                    { // ランクラン
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1PcInstance clanPc = (L1PcInstance)L1World
                                .getInstance().findObject( _targetID );
                        if ( clanPc != null )
                        {
                            if ( pc.getMap().isEscapable() || pc.isGm() )
                            {
                                bool castle_area = L1CastleLocation
                                        .checkInAllWarArea(
                                    // いずれかの城エリア
                                                clanPc.getX(), clanPc.getY(),
                                                clanPc.getMapId() );
                                if ( ( clanPc.getMapId() == 0
                                        || clanPc.getMapId() == 4 || clanPc
                                        .getMapId() == 304 )
                                        && castle_area == false )
                                {
                                    L1Teleport.teleport( pc, clanPc.getX(),
                                            clanPc.getY(), clanPc.getMapId(),
                                            5, true );
                                }
                                else
                                {
                                    // \f1あなたのパートナーは今あなたが行けない所でプレイ中です。
                                    pc.sendPackets( new S_ServerMessage( 547 ) );
                                }
                            }
                            else
                            {
                                // 周辺のエネルギーがテレポートを妨害しています。そのため、ここでテレポートは使用できません。
                                pc.sendPackets( new S_ServerMessage( 647 ) );
                                L1Teleport.teleport( pc, pc.getX(), pc.getY(),
                                        pc.getMapId(), pc.getHeading(), false );
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.CREATE_MAGICAL_WEAPON )
                    { // クリエイト
                        // マジカル ウェポン
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1ItemInstance item = pc.getInventory().getItem( _itemobjid );
                        if ( item != null && item.getItem().getType2() == 1 )
                        {
                            int item_type = item.getItem().getType2();
                            int safe_enchant = item.getItem().get_safeenchant();
                            int enchant_level = item.getEnchantLevel();
                            String item_name = item.getName();
                            if ( safe_enchant < 0 )
                            { // 強化不可
                                pc.sendPackets( // \f1何も起きませんでした。
                                        new S_ServerMessage( 79 ) );
                            }
                            else if ( safe_enchant == 0 )
                            { // 安全圏+0
                                pc.sendPackets( // \f1何も起きませんでした。
                                        new S_ServerMessage( 79 ) );
                            }
                            else if ( item_type == 1 && enchant_level == 0 )
                            {
                                if ( !item.isIdentified() )
                                {// 未鑑定
                                    pc.sendPackets( // \f1%0が%2%1光ります。
                                            new S_ServerMessage( 161, item_name,
                                                    "$245", "$247" ) );
                                }
                                else
                                {
                                    item_name = "+0 " + item_name;
                                    pc.sendPackets( // \f1%0が%2%1光ります。
                                            new S_ServerMessage( 161, "+0 "
                                                    + item_name, "$245", "$247" ) );
                                }
                                item.setEnchantLevel( 1 );
                                pc.getInventory().updateItem( item,
                                        L1PcInventory.COL_ENCHANTLVL );
                            }
                            else
                            {
                                pc.sendPackets( // \f1何も起きませんでした。
                                        new S_ServerMessage( 79 ) );
                            }
                        }
                        else
                        {
                            pc.sendPackets( // \f1何も起きませんでした。
                                    new S_ServerMessage( 79 ) );
                        }
                    }
                    else if ( _skillId == L1SkillId.BRING_STONE )
                    { // ブリング ストーン
                        L1PcInstance pc = (L1PcInstance)cha;
                        Random random = new Random();
                        L1ItemInstance item = pc.getInventory().getItem(
                                _itemobjid );
                        if ( item != null )
                        {
                            int dark = (int)( 10 + ( pc.getLevel() * 0.8 ) + ( pc
                                    .getWis() - 6 ) * 1.2 );
                            int brave = (int)( dark / 2.1 );
                            int wise = (int)( brave / 2.0 );
                            int kayser = (int)( wise / 1.9 );
                            int chance = random.Next( 100 ) + 1;
                            if ( item.getItem().getItemId() == 40320 )
                            {
                                pc.getInventory().removeItem( item, 1 );
                                if ( dark >= chance )
                                {
                                    pc.getInventory().storeItem( 40321, 1 );
                                    pc.sendPackets( new S_ServerMessage( 403, "$2475" ) ); // %0を手に入れました。
                                }
                                else
                                {
                                    pc.sendPackets( new S_ServerMessage( 280 ) ); // \f1魔法が失敗しました。
                                }
                            }
                            else if ( item.getItem().getItemId() == 40321 )
                            {
                                pc.getInventory().removeItem( item, 1 );
                                if ( brave >= chance )
                                {
                                    pc.getInventory().storeItem( 40322, 1 );
                                    pc.sendPackets( new S_ServerMessage( 403,
                                            "$2476" ) ); // %0を手に入れました。
                                }
                                else
                                {
                                    pc.sendPackets( new S_ServerMessage( 280 ) ); // \f1魔法が失敗しました。
                                }
                            }
                            else if ( item.getItem().getItemId() == 40322 )
                            {
                                pc.getInventory().removeItem( item, 1 );
                                if ( wise >= chance )
                                {
                                    pc.getInventory().storeItem( 40323, 1 );
                                    pc.sendPackets( new S_ServerMessage( 403,
                                            "$2477" ) ); // %0を手に入れました。
                                }
                                else
                                {
                                    pc.sendPackets( new S_ServerMessage( 280 ) ); // \f1魔法が失敗しました。
                                }
                            }
                            else if ( item.getItem().getItemId() == 40323 )
                            {
                                pc.getInventory().removeItem( item, 1 );
                                if ( kayser >= chance )
                                {
                                    pc.getInventory().storeItem( 40324, 1 );
                                    pc.sendPackets( new S_ServerMessage( 403,
                                            "$2478" ) ); // %0を手に入れました。
                                }
                                else
                                {
                                    pc.sendPackets( new S_ServerMessage( 280 ) ); // \f1魔法が失敗しました。
                                }
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.SUMMON_MONSTER )
                    { // サモンモンスター
                        L1PcInstance pc = (L1PcInstance)cha;
                        int level = pc.getLevel();
                        int[] summons;
                        if ( pc.getMap().isRecallPets() || pc.isGm() )
                        {
                            if ( pc.getInventory().checkEquipped( 20284 ) )
                            {
                                pc.sendPackets( new S_ShowSummonList( pc.getId() ) );
                                if ( !pc.isSummonMonster() )
                                {
                                    pc.setSummonMonster( true );
                                }
                            }
                            else
                            {
                                /*
                                 * summons = new int[] { 81083, 81084, 81085, 81086, 81087, 81088, 81089 };
                                 */
                                summons = new int[] { 81210, 81213, 81216, 81219, 81222, 81225, 81228 };
                                int summonid = 0;
                                // int summoncost = 6;
                                int summoncost = 8;
                                int levelRange = 32;
                                for ( int i = 0; i < summons.Length; i++ )
                                { // 該当ＬＶ範囲検索
                                    if ( level < levelRange || i == summons.Length - 1 )
                                    {
                                        summonid = summons[i];
                                        break;
                                    }
                                    levelRange += 4;
                                }

                                int petcost = 0;
                                //Object[] petlist = pc.getPetList().values()
                                //        .toArray();
                                foreach ( L1NpcInstance pet in pc.getPetList().Values )
                                {
                                    // 現在のペットコスト
                                    petcost += pet.getPetcost();
                                }
                                int pcCha = pc.getCha();
                                if ( pcCha > 34 )
                                { // max count = 5
                                    pcCha = 34;
                                }
                                int charisma = pcCha + 6 - petcost;
                                // int charisma = pc.getCha() + 6 - petcost;
                                int summoncount = charisma / summoncost;
                                L1Npc npcTemp = NpcTable.getInstance()
                                        .getTemplate( summonid );
                                for ( int i = 0; i < summoncount; i++ )
                                {
                                    L1SummonInstance summon = new L1SummonInstance( npcTemp, pc );
                                    summon.setPetcost( summoncost );
                                }
                            }
                        }
                        else
                        {
                            // \f1何も起きませんでした。
                            pc.sendPackets( new S_ServerMessage( 79 ) );
                        }
                    }
                    else if ( _skillId == L1SkillId.LESSER_ELEMENTAL
                          || _skillId == L1SkillId.GREATER_ELEMENTAL )
                    { // レッサーエレメンタル、グレーターエレメンタル
                        L1PcInstance pc = (L1PcInstance)cha;
                        int attr = pc.getElfAttr();
                        if ( attr != 0 )
                        { // 無属性でなければ実行
                            if ( pc.getMap().isRecallPets() || pc.isGm() )
                            {
                                int petcost = 0;
                                //Object[] petlist = pc.getPetList().values()
                                //        .toArray();
                                foreach ( L1NpcInstance pet in pc.getPetList().Values )
                                {
                                    // 現在のペットコスト
                                    petcost += pet.getPetcost();
                                }

                                if ( petcost == 0 )
                                { // 1匹も所属NPCがいなければ実行
                                    int summonid = 0;
                                    int[] summons;
                                    if ( _skillId == L1SkillId.LESSER_ELEMENTAL )
                                    { // レッサーエレメンタル[地,火,水,風]
                                        summons = new int[] { 45306, 45303,
												45304, 45305 };
                                    }
                                    else
                                    {
                                        // グレーターエレメンタル[地,火,水,風]
                                        summons = new int[] { 81053, 81050,
												81051, 81052 };
                                    }
                                    int npcattr = 1;
                                    for ( int i = 0; i < summons.Length; i++ )
                                    {
                                        if ( npcattr == attr )
                                        {
                                            summonid = summons[i];
                                            i = summons.Length;
                                        }
                                        npcattr *= 2;
                                    }
                                    // 特殊設定の場合ランダムで出現
                                    if ( summonid == 0 )
                                    {
                                        Random random = new Random();
                                        int k3 = random.Next( 4 );
                                        summonid = summons[k3];
                                    }

                                    L1Npc npcTemp = NpcTable.getInstance()
                                            .getTemplate( summonid );
                                    L1SummonInstance summon = new L1SummonInstance(
                                            npcTemp, pc );
                                    summon.setPetcost( pc.getCha() + 7 ); // 精霊の他にはNPCを所属させられない
                                }
                            }
                            else
                            {
                                // \f1何も起きませんでした。
                                pc.sendPackets( new S_ServerMessage( 79 ) );
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.ABSOLUTE_BARRIER )
                    { // アブソルート バリア
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.stopHpRegeneration();
                        pc.stopMpRegeneration();
                        pc.stopMpRegenerationByDoll();
                    }

                    // ★★★ 変化系スキル（エンチャント） ★★★
                    if ( _skillId == L1SkillId.LIGHT )
                    { // ライト
                        // addMagicList()後に、turnOnOffLight()でパケット送信
                    }
                    else if ( _skillId == L1SkillId.GLOWING_AURA )
                    { // グローウィング オーラ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addHitup( 5 );
                        pc.addBowHitup( 5 );
                        pc.addMr( 20 );
                        pc.sendPackets( new S_SPMR( pc ) );
                        pc.sendPackets( new S_SkillIconAura( 113, _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.SHINING_AURA )
                    { // シャイニング オーラ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -8 );
                        pc.sendPackets( new S_SkillIconAura( 114,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.BRAVE_AURA )
                    { // ブレイブ オーラ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 5 );
                        pc.sendPackets( new S_SkillIconAura( 116, _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.SHIELD )
                    { // シールド
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -2 );
                        pc.sendPackets( new S_SkillIconShield( 5, _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.SHADOW_ARMOR )
                    { // シャドウ アーマー
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -3 );
                        pc.sendPackets( new S_SkillIconShield( 3, _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.DRESS_DEXTERITY )
                    { // ドレス デクスタリティー
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDex( (byte)2 );
                        pc.sendPackets( new S_Dexup( pc, 2, _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.DRESS_MIGHTY )
                    { // ドレス マイティー
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addStr( (byte)2 );
                        pc
                                .sendPackets( new S_Strup( pc, 2,
                                        _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.SHADOW_FANG )
                    { // シャドウ ファング
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1ItemInstance item = pc.getInventory()
                                .getItem( _itemobjid );
                        if ( item != null && item.getItem().getType2() == 1 )
                        {
                            item.setSkillWeaponEnchant( pc, _skillId,
                                    _skill.getBuffDuration() * 1000 );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 79 ) );
                        }
                    }
                    else if ( _skillId == L1SkillId.ENCHANT_WEAPON )
                    { // エンチャント ウェポン
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1ItemInstance item = pc.getInventory()
                                .getItem( _itemobjid );
                        if ( item != null && item.getItem().getType2() == 1 )
                        {
                            pc.sendPackets( new S_ServerMessage( 161,
                                    item.getLogName(), "$245", "$247" ) );
                            item.setSkillWeaponEnchant( pc, _skillId,
                                    _skill.getBuffDuration() * 1000 );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 79 ) );
                        }
                    }
                    else if ( _skillId == L1SkillId.HOLY_WEAPON // ホーリー ウェポン
                          || _skillId == L1SkillId.BLESS_WEAPON )
                    { // ブレス ウェポン
                        if ( !( cha is L1PcInstance ) )
                        {
                            return;
                        }
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( pc.getWeapon() == null )
                        {
                            pc.sendPackets( new S_ServerMessage( 79 ) );
                            return;
                        }
                        foreach ( L1ItemInstance item in pc.getInventory()
                                .getItems() )
                        {
                            if ( pc.getWeapon().Equals( item ) )
                            {
                                pc.sendPackets( new S_ServerMessage( 161, item.getLogName(), "$245", "$247" ) );
                                item.setSkillWeaponEnchant( pc, _skillId, _skill.getBuffDuration() * 1000 );
                                return;
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.BLESSED_ARMOR )
                    { // ブレスド アーマー
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1ItemInstance item = pc.getInventory().getItem( _itemobjid );
                        if ( item != null && item.getItem().getType2() == 2
                                && item.getItem().getType() == 2 )
                        {
                            pc.sendPackets( new S_ServerMessage( 161, item
                                    .getLogName(), "$245", "$247" ) );
                            item.setSkillArmorEnchant( pc, _skillId,
                                    _skill.getBuffDuration() * 1000 );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 79 ) );
                        }
                    }
                    else if ( _skillId == L1SkillId.EARTH_BLESS )
                    { // アース ブレス
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -7 );
                        pc.sendPackets( new S_SkillIconShield( 7,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.RESIST_MAGIC )
                    { // レジスト マジック
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addMr( 10 );
                        pc.sendPackets( new S_SPMR( pc ) );
                    }
                    else if ( _skillId == L1SkillId.CLEAR_MIND )
                    { // クリアー マインド
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addWis( (byte)3 );
                        pc.resetBaseMr();
                    }
                    else if ( _skillId == L1SkillId.RESIST_ELEMENTAL )
                    { // レジスト エレメント
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addWind( 10 );
                        pc.addWater( 10 );
                        pc.addFire( 10 );
                        pc.addEarth( 10 );
                        pc.sendPackets( new S_OwnCharAttrDef( pc ) );
                    }
                    else if ( _skillId == L1SkillId.BODY_TO_MIND )
                    { // ボディ トゥ マインド
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.setCurrentMp( pc.getCurrentMp() + 2 );
                    }
                    else if ( _skillId == L1SkillId.BLOODY_SOUL )
                    { // ブラッディ ソウル
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.setCurrentMp( pc.getCurrentMp() + 12 );
                    }
                    else if ( _skillId == L1SkillId.ELEMENTAL_PROTECTION )
                    { // エレメンタルプロテクション
                        L1PcInstance pc = (L1PcInstance)cha;
                        int attr = pc.getElfAttr();
                        if ( attr == 1 )
                        {
                            pc.addEarth( 50 );
                        }
                        else if ( attr == 2 )
                        {
                            pc.addFire( 50 );
                        }
                        else if ( attr == 4 )
                        {
                            pc.addWater( 50 );
                        }
                        else if ( attr == 8 )
                        {
                            pc.addWind( 50 );
                        }
                    }
                    else if ( _skillId == L1SkillId.INVISIBILITY
                          || _skillId == L1SkillId.BLIND_HIDING )
                    { // インビジビリティ、ブラインドハイディング
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_Invis( pc.getId(), 1 ) );
                        pc.broadcastPacketForFindInvis( new S_RemoveObject( pc ), false );
                        // pc.broadcastPacket(new S_RemoveObject(pc));
                    }
                    else if ( _skillId == L1SkillId.IRON_SKIN )
                    { // アイアン スキン
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -10 );
                        pc.sendPackets( new S_SkillIconShield( 10,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.EARTH_SKIN )
                    { // アース スキン
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -6 );
                        pc.sendPackets( new S_SkillIconShield( 6,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_STR )
                    { // フィジカルエンチャント：STR
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addStr( (byte)5 );
                        pc
                                .sendPackets( new S_Strup( pc, 5,
                                        _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.PHYSICAL_ENCHANT_DEX )
                    { // フィジカルエンチャント：DEX
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDex( (byte)5 );
                        pc
                                .sendPackets( new S_Dexup( pc, 5,
                                        _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.FIRE_WEAPON )
                    { // ファイアー ウェポン
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 4 );
                        pc.sendPackets( new S_SkillIconAura( 147,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.FIRE_BLESS )
                    { // ファイアー ブレス
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 4 );
                        pc.sendPackets( new S_SkillIconAura( 154,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.BURNING_WEAPON )
                    { // バーニング ウェポン
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 6 );
                        pc.addHitup( 3 );
                        pc.sendPackets( new S_SkillIconAura( 162,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.WIND_SHOT )
                    { // ウィンド ショット
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addBowHitup( 6 );
                        pc.sendPackets( new S_SkillIconAura( 148,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.STORM_EYE )
                    { // ストーム アイ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addBowHitup( 2 );
                        pc.addBowDmgup( 3 );
                        pc.sendPackets( new S_SkillIconAura( 155,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.STORM_SHOT )
                    { // ストーム ショット
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addBowDmgup( 5 );
                        pc.addBowHitup( -1 );
                        pc.sendPackets( new S_SkillIconAura( 165,
                                _getBuffIconDuration ) );
                    }
                    else if ( _skillId == L1SkillId.BERSERKERS )
                    { // バーサーカー
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( 10 );
                        pc.addDmgup( 5 );
                        pc.addHitup( 2 );
                    }
                    else if ( _skillId == L1SkillId.SHAPE_CHANGE )
                    { // シェイプ チェンジ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.sendPackets( new S_ShowPolyList( pc.getId() ) );
                        if ( !pc.isShapeChange() )
                        {
                            pc.setShapeChange( true );
                        }
                    }
                    else if ( _skillId == L1SkillId.ADVANCE_SPIRIT )
                    { // アドバンスド スピリッツ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.setAdvenHp( pc.getBaseMaxHp() / 5 );
                        pc.setAdvenMp( pc.getBaseMaxMp() / 5 );
                        pc.addMaxHp( pc.getAdvenHp() );
                        pc.addMaxMp( pc.getAdvenMp() );
                        pc.sendPackets( new S_HPUpdate( pc.getCurrentHp(), pc.getMaxHp() ) );
                        if ( pc.isInParty() )
                        { // パーティー中
                            pc.getParty().updateMiniHP( pc );
                        }
                        pc.sendPackets( new S_MPUpdate( pc.getCurrentMp(), pc.getMaxMp() ) );
                    }
                    else if ( _skillId == L1SkillId.GREATER_HASTE )
                    { // グレーター ヘイスト
                        L1PcInstance pc = (L1PcInstance)cha;
                        if ( pc.getHasteItemEquipped() > 0 )
                        {
                            continue;
                        }
                        if ( pc.getMoveSpeed() != 2 )
                        { // スロー中以外
                            pc.setDrink( false );
                            pc.setMoveSpeed( 1 );
                            pc.sendPackets( new S_SkillHaste( pc.getId(), 1, _getBuffIconDuration ) );
                            pc.broadcastPacket( new S_SkillHaste( pc.getId(), 1, 0 ) );
                        }
                        else
                        { // スロー中
                            int skillNum = 0;
                            if ( pc.hasSkillEffect( L1SkillId.SLOW ) )
                            {
                                skillNum = L1SkillId.SLOW;
                            }
                            else if ( pc.hasSkillEffect( L1SkillId.MASS_SLOW ) )
                            {
                                skillNum = L1SkillId.MASS_SLOW;
                            }
                            else if ( pc.hasSkillEffect( L1SkillId.ENTANGLE ) )
                            {
                                skillNum = L1SkillId.ENTANGLE;
                            }
                            if ( skillNum != 0 )
                            {
                                pc.removeSkillEffect( skillNum );
                                pc.removeSkillEffect( L1SkillId.GREATER_HASTE );
                                pc.setMoveSpeed( 0 );
                                continue;
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.HOLY_WALK
                          || _skillId == L1SkillId.MOVING_ACCELERATION
                          || _skillId == L1SkillId.WIND_WALK )
                    { // ホーリーウォーク、ムービングアクセレーション、ウィンドウォーク
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.setBraveSpeed( 4 );
                        pc.sendPackets( new S_SkillBrave( pc.getId(), 4, _getBuffIconDuration ) );
                        pc.broadcastPacket( new S_SkillBrave( pc.getId(), 4, 0 ) );
                    }
                    else if ( _skillId == L1SkillId.BLOODLUST )
                    { // ブラッドラスト
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.setBraveSpeed( 6 );
                        pc.sendPackets( new S_SkillBrave( pc.getId(), 6, _getBuffIconDuration ) );
                        pc.broadcastPacket( new S_SkillBrave( pc.getId(), 6, 0 ) );
                    }
                    else if ( _skillId == L1SkillId.AWAKEN_ANTHARAS )
                    { // 覚醒：アンタラス
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1Awake.start( pc, _skillId );
                    }
                    else if ( _skillId == L1SkillId.AWAKEN_FAFURION )
                    { // 覚醒：パプリオン
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1Awake.start( pc, _skillId );
                    }
                    else if ( _skillId == L1SkillId.AWAKEN_VALAKAS )
                    { // 覚醒：ヴァラカス
                        L1PcInstance pc = (L1PcInstance)cha;
                        L1Awake.start( pc, _skillId );
                    }
                    else if ( _skillId == L1SkillId.ILLUSION_OGRE )
                    { // イリュージョン：オーガ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 4 );
                        pc.addHitup( 4 );
                        pc.addBowDmgup( 4 );
                        pc.addBowHitup( 4 );
                    }
                    else if ( _skillId == L1SkillId.ILLUSION_LICH )
                    { // イリュージョン：リッチ
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addSp( 2 );
                        pc.sendPackets( new S_SPMR( pc ) );
                    }
                    else if ( _skillId == L1SkillId.ILLUSION_DIA_GOLEM )
                    { // イリュージョン：ダイアモンドゴーレム
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addAc( -20 );
                    }
                    else if ( _skillId == L1SkillId.ILLUSION_AVATAR )
                    { // イリュージョン：アバター
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addDmgup( 10 );
                        pc.addBowDmgup( 10 );
                    }
                    else if ( _skillId == L1SkillId.INSIGHT )
                    { // インサイト
                        L1PcInstance pc = (L1PcInstance)cha;
                        pc.addStr( (byte)1 );
                        pc.addCon( (byte)1 );
                        pc.addDex( (byte)1 );
                        pc.addWis( (byte)1 );
                        pc.addInt( (byte)1 );
                    }
                }

                // ●●●● NPCにしか効果のないスキル ●●●●
                if ( _calcType == PC_NPC || _calcType == NPC_NPC )
                {
                    // ★★★ ペット系スキル ★★★
                    if ( _skillId == L1SkillId.TAMING_MONSTER
                            && ( (L1MonsterInstance)cha ).getNpcTemplate().isTamable() )
                    { // テイミングモンスター
                        int petcost = 0;
                        //Object[] petlist = _user.getPetList().values().toArray();
                        foreach ( L1NpcInstance pet in _user.getPetList().Values )
                        {
                            // 現在のペットコスト
                            petcost += pet.getPetcost();
                        }
                        int charisma = _user.getCha();
                        if ( _player.isElf() )
                        { // エルフ
                            if ( charisma > 30 )
                            { // max count = 7
                                charisma = 30;
                            }
                            charisma += 12;
                        }
                        else if ( _player.isWizard() )
                        { // ウィザード
                            if ( charisma > 36 )
                            { // max count = 7
                                charisma = 36;
                            }
                            charisma += 6;
                        }
                        charisma -= petcost;
                        if ( charisma >= 6 )
                        { // ペットコストの確認
                            L1SummonInstance summon = new L1SummonInstance( _targetNpc, _user, false );
                            _target = summon; // ターゲット入替え
                        }
                        else
                        {
                            _player.sendPackets( new S_ServerMessage( 319 ) ); // \f1これ以上のモンスターを操ることはできません。
                        }
                    }
                    else if ( _skillId == L1SkillId.CREATE_ZOMBIE )
                    { // クリエイトゾンビ
                        int petcost = 0;
                        //Object[] petlist = _user.getPetList().values()
                        //        .toArray();
                        foreach ( L1NpcInstance pet in _user.getPetList().Values )
                        {
                            // 現在のペットコスト
                            petcost += pet.getPetcost();
                        }
                        int charisma = _user.getCha();
                        if ( _player.isElf() )
                        { // エルフ
                            if ( charisma > 30 )
                            { // max count = 7
                                charisma = 30;
                            }
                            charisma += 12;
                        }
                        else if ( _player.isWizard() )
                        { // ウィザード
                            if ( charisma > 36 )
                            { // max count = 7
                                charisma = 36;
                            }
                            charisma += 6;
                        }
                        charisma -= petcost;
                        if ( charisma >= 6 )
                        { // ペットコストの確認
                            L1SummonInstance summon = new L1SummonInstance(
                                    _targetNpc, _user, true );
                            _target = summon; // ターゲット入替え
                        }
                        else
                        {
                            _player.sendPackets( new S_ServerMessage( 319 ) ); // \f1これ以上のモンスターを操ることはできません。
                        }
                    }
                    else if ( _skillId == L1SkillId.WEAK_ELEMENTAL )
                    { // ウィーク エレメンタル
                        if ( cha is L1MonsterInstance )
                        {
                            L1Npc npcTemp = ( (L1MonsterInstance)cha ).getNpcTemplate();
                            int weakAttr = npcTemp.get_weakAttr();
                            if ( ( weakAttr & 1 ) == 1 )
                            { // 地
                                cha.broadcastPacket( new S_SkillSound( cha.getId(), 2169 ) );
                            }
                            if ( ( weakAttr & 2 ) == 2 )
                            { // 火
                                cha.broadcastPacket( new S_SkillSound( cha.getId(), 2167 ) );
                            }
                            if ( ( weakAttr & 4 ) == 4 )
                            { // 水
                                cha.broadcastPacket( new S_SkillSound( cha.getId(), 2166 ) );
                            }
                            if ( ( weakAttr & 8 ) == 8 )
                            { // 風
                                cha.broadcastPacket( new S_SkillSound( cha.getId(), 2168 ) );
                            }
                        }
                    }
                    else if ( _skillId == L1SkillId.RETURN_TO_NATURE )
                    { // リターントゥネイチャー
                        if ( Config.RETURN_TO_NATURE
                                && cha is L1SummonInstance )
                        {
                            L1SummonInstance summon = (L1SummonInstance)cha;
                            summon.broadcastPacket( new S_SkillSound( summon.getId(), 2245 ) );
                            summon.returnToNature();
                        }
                        else
                        {
                            if ( _user is L1PcInstance )
                            {
                                _player.sendPackets( new S_ServerMessage( 79 ) );
                            }
                        }
                    }
                }

                // ■■■■ 個別処理ここまで ■■■■

                if ( _skill.getType() == L1Skills.TYPE_HEAL
                        && _calcType == PC_NPC && undeadType == 1 )
                {
                    dmg *= -1; // もし、アンデットで回復系スキルならばダメージになる。
                }

                if ( _skill.getType() == L1Skills.TYPE_HEAL
                        && _calcType == PC_NPC && undeadType == 3 )
                {
                    dmg = 0; // もし、アンデット系ボスで回復系スキルならば無効
                }

                if ( ( cha is L1TowerInstance
                        || cha is L1DoorInstance ) && dmg < 0 )
                { // ガーディアンタワー、ドアにヒールを使用
                    dmg = 0;
                }

                if ( dmg != 0 || drainMana != 0 )
                {
                    _magic.commit( dmg, drainMana ); // ダメージ系、回復系の値をターゲットにコミットする。
                }

                // ヒール系の他に、別途回復した場合（V-Tなど）
                if ( heal > 0 )
                {
                    if ( ( heal + _user.getCurrentHp() ) > _user.getMaxHp() )
                    {
                        _user.setCurrentHp( _user.getMaxHp() );
                    }
                    else
                    {
                        _user.setCurrentHp( heal + _user.getCurrentHp() );
                    }
                }

                if ( cha is L1PcInstance )
                { // ターゲットがPCならば、ACとステータスを送信
                    L1PcInstance pc = (L1PcInstance)cha;
                    pc.turnOnOffLight();
                    pc.sendPackets( new S_OwnCharAttrDef( pc ) );
                    pc.sendPackets( new S_OwnCharStatus( pc ) );
                    sendHappenMessage( pc ); // ターゲットにメッセージを送信
                }

                addMagicList( cha, false ); // ターゲットに魔法の効果時間を設定

                if ( cha is L1PcInstance )
                { // ターゲットがPCならば、ライト状態を更新
                    L1PcInstance pc = (L1PcInstance)cha;
                    pc.turnOnOffLight();
                }
            }

            if ( _skillId == L1SkillId.DETECTION || _skillId == L1SkillId.COUNTER_DETECTION )
            { // ディテクション、カウンターディテクション
                detection( _player );
            }


        }

        /**
         * キャンセレーションで解除できないスキルかを返す。
         */
        private bool isNotCancelable( int skillNum )
        {
            return skillNum == L1SkillId.ENCHANT_WEAPON || skillNum == L1SkillId.BLESSED_ARMOR
                || skillNum == L1SkillId.ABSOLUTE_BARRIER || skillNum == L1SkillId.ADVANCE_SPIRIT
                || skillNum == L1SkillId.SHOCK_STUN || skillNum == L1SkillId.SHADOW_FANG
                || skillNum == L1SkillId.REDUCTION_ARMOR || skillNum == L1SkillId.SOLID_CARRIAGE
                || skillNum == L1SkillId.COUNTER_BARRIER || skillNum == L1SkillId.AWAKEN_ANTHARAS
                || skillNum == L1SkillId.AWAKEN_FAFURION || skillNum == L1SkillId.AWAKEN_VALAKAS;
        }

        private void detection( L1PcInstance pc )
        {
            if ( !pc.isGmInvis() && pc.isInvisble() )
            { // 自分
                pc.delInvis();
                pc.beginInvisTimer();
            }

            foreach ( L1PcInstance tgt in L1World.getInstance().getVisiblePlayer( pc ) )
            {
                if ( !tgt.isGmInvis() && tgt.isInvisble() )
                {
                    tgt.delInvis();
                }
            }
            L1WorldTraps.getInstance().onDetection( pc );
        }

        // ターゲットについて計算する必要があるか返す
        private bool isTargetCalc( L1Character cha )
        {
            // 攻撃魔法のNon－PvP判定
            if ( _skill.getTarget().Equals( "attack" ) && _skillId != 18 )
            { // 攻撃魔法
                if ( isPcSummonPet( cha ) )
                { // 対象がPC、サモン、ペット
                    if ( _player.getZoneType() == 1 || cha.getZoneType() == 1 // 攻撃する側または攻撃される側がセーフティーゾーン
                            || _player.checkNonPvP( _player, cha ) )
                    { // Non-PvP設定
                        return false;
                    }
                }
            }

            // フォグオブスリーピングは自分自身は対象外
            if ( _skillId == L1SkillId.FOG_OF_SLEEPING && _user.getId() == cha.getId() )
            {
                return false;
            }

            // マススローは自分自身と自分のペットは対象外
            if ( _skillId == L1SkillId.MASS_SLOW )
            {
                if ( _user.getId() == cha.getId() )
                {
                    return false;
                }
                if ( cha is L1SummonInstance )
                {
                    L1SummonInstance summon = (L1SummonInstance)cha;
                    if ( _user.getId() == summon.getMaster().getId() )
                    {
                        return false;
                    }
                }
                else if ( cha is L1PetInstance )
                {
                    L1PetInstance pet = (L1PetInstance)cha;
                    if ( _user.getId() == pet.getMaster().getId() )
                    {
                        return false;
                    }
                }
            }

            // マステレポートは自分自身のみ対象（同時にクラン員もテレポートさせる）
            if ( _skillId == L1SkillId.MASS_TELEPORT )
            {
                if ( _user.getId() != cha.getId() )
                {
                    return false;
                }
            }

            return true;
        }

        // 対象がPC、サモン、ペットかを返す
        private bool isPcSummonPet( L1Character cha )
        {
            if ( _calcType == PC_PC )
            { // 対象がPC
                return true;
            }

            if ( _calcType == PC_NPC )
            {
                if ( cha is L1SummonInstance )
                { // 対象がサモン
                    L1SummonInstance summon = (L1SummonInstance)cha;
                    if ( summon.isExsistMaster() )
                    { // マスターが居る
                        return true;
                    }
                }
                if ( cha is L1PetInstance )
                { // 対象がペット
                    return true;
                }
            }
            return false;
        }

        // ターゲットに対して必ず失敗になるか返す
        private bool isTargetFailure( L1Character cha )
        {
            bool isTU = false;
            bool isErase = false;
            bool isManaDrain = false;
            int undeadType = 0;

            if ( cha is L1TowerInstance || cha is L1DoorInstance )
            { // ガーディアンタワー、ドアには確率系スキル無効
                return true;
            }

            if ( cha is L1PcInstance )
            { // 対PCの場合
                if ( _calcType == PC_PC && _player.checkNonPvP( _player, cha ) )
                { // Non-PvP設定
                    L1PcInstance pc = (L1PcInstance)cha;
                    if ( _player.getId() == pc.getId()
                            || ( pc.getClanid() != 0 && _player.getClanid() == pc
                                    .getClanid() ) )
                    {
                        return false;
                    }
                    return true;
                }
                return false;
            }

            if ( cha is L1MonsterInstance )
            { // ターンアンデット可能か判定
                isTU = ( (L1MonsterInstance)cha ).getNpcTemplate().get_IsTU();
            }

            if ( cha is L1MonsterInstance )
            { // イレースマジック可能か判定
                isErase = ( (L1MonsterInstance)cha ).getNpcTemplate().get_IsErase();
            }

            if ( cha is L1MonsterInstance )
            { // アンデットの判定
                undeadType = ( (L1MonsterInstance)cha ).getNpcTemplate()
                        .get_undead();
            }

            // マナドレインが可能か？
            if ( cha is L1MonsterInstance )
            {
                isManaDrain = true;
            }
            /*
             * 成功除外条件１：T-Uが成功したが、対象がアンデットではない。 成功除外条件２：T-Uが成功したが、対象にはターンアンデット無効。
             * 成功除外条件３：スロー、マススロー、マナドレイン、エンタングル、イレースマジック、ウィンドシャックル無効
             * 成功除外条件４：マナドレインが成功したが、モンスター以外の場合
             */
            if ( ( _skillId == L1SkillId.TURN_UNDEAD && ( undeadType == 0 || undeadType == 2 ) )
             || ( _skillId == L1SkillId.TURN_UNDEAD && isTU == false )
            || ( ( _skillId == L1SkillId.ERASE_MAGIC || _skillId == L1SkillId.SLOW
              || _skillId == L1SkillId.MANA_DRAIN || _skillId == L1SkillId.MASS_SLOW
              || _skillId == L1SkillId.ENTANGLE || _skillId == L1SkillId.WIND_SHACKLE ) && isErase == false )
             || ( _skillId == L1SkillId.MANA_DRAIN && isManaDrain == false ) )
            {
                return true;
            }
            return false;
        }

        // カウンターマジックが発動したか返す
        private bool isUseCounterMagic( L1Character cha )
        {
            // カウンターマジック有効なスキルでカウンターマジック中
            if ( _isCounterMagic && cha.hasSkillEffect( L1SkillId.COUNTER_MAGIC ) )
            {
                cha.removeSkillEffect( L1SkillId.COUNTER_MAGIC );
                int castgfx = SkillsTable.getInstance().getTemplate( L1SkillId.COUNTER_MAGIC ).getCastGfx();
                cha.broadcastPacket( new S_SkillSound( cha.getId(), castgfx ) );
                if ( cha is L1PcInstance )
                {
                    L1PcInstance pc = (L1PcInstance)cha;
                    pc.sendPackets( new S_SkillSound( pc.getId(), castgfx ) );
                }
                return true;
            }
            return false;
        }
    }
}
